diff --git a/src/main/kotlin/usecase/ReportGenerationUseCase.kt b/src/main/kotlin/usecase/ReportGenerationUseCase.kt index aaa54f7..0e6e07f 100644 --- a/src/main/kotlin/usecase/ReportGenerationUseCase.kt +++ b/src/main/kotlin/usecase/ReportGenerationUseCase.kt @@ -10,16 +10,7 @@ package usecase import entity.healthcareuser.HealthcareUser import entity.healthcareuser.PatientVitalSigns -import entity.healthcareuser.VitalSign import entity.healthprofessional.HealthProfessionalID -import entity.measurements.AggregateData -import entity.measurements.Humidity -import entity.measurements.LightUnit -import entity.measurements.Luminosity -import entity.measurements.Percentage -import entity.measurements.Presence -import entity.measurements.Temperature -import entity.measurements.TemperatureUnit import entity.medicaldevice.ImplantableMedicalDevice import entity.medicaldevice.MedicalTechnologyUsage import entity.process.SurgicalProcess @@ -30,9 +21,11 @@ import entity.report.SurgeryReport import entity.room.RoomEnvironmentalData import entity.room.RoomType import entity.tracking.TrackingInfo +import usecase.aggregation.AggregateRoomEnvironmentalDataExtractor +import usecase.aggregation.AggregateVitalSignsExtractor +import usecase.aggregation.util.CollectionExtensions.takePeriod import java.time.Instant import java.util.Date -import kotlin.math.pow /** * This use case has the objective of generate the [SurgeryReport] based on the information of the @@ -55,106 +48,47 @@ class ReportGenerationUseCase( private val medicalTechnologyUsage: Set = setOf(), ) : UseCase { override fun execute(): SurgeryReport = SurgeryReport( - surgicalProcess.id, + this.surgicalProcess.id, Date.from( - surgicalProcess.processStates.first { + this.surgicalProcess.processStates.first { it.second == SurgicalProcessState.PreSurgery(SurgicalProcessStep.PATIENT_IN_PREPARATION) }.first, ), - surgicalProcess.description, - surgicalProcess.inChargeHealthProfessional, - surgicalProcess.patientID, - healthcareUser, + this.surgicalProcess.description, + this.surgicalProcess.inChargeHealthProfessional, + this.surgicalProcess.patientID, + this.healthcareUser, computeAggregateData(), - consumedImplantableMedicalDevices, - medicalTechnologyUsage, - healthProfessionalTrackingInformation, + this.consumedImplantableMedicalDevices, + this.medicalTechnologyUsage, + this.healthProfessionalTrackingInformation, ) private fun computeAggregateData(): Map { val stateSorted = this.surgicalProcess.processStates.sortedBy { it.first } - val finalDateIterator = stateSorted.map { it.first }.sorted().iterator() + val finalDateIterator = stateSorted.map { it.first }.iterator() - return stateSorted.associate { - val dateTimeFrom = it.first + return stateSorted.associate { stateEntry -> + val dateTimeFrom = stateEntry.first val dateTimeTo = if (finalDateIterator.hasNext()) finalDateIterator.next() else null val vitalSignsInPeriod = this.patientVitalSigns .takePeriod(dateTimeFrom, dateTimeTo) .map { pair -> pair.second } - val environmentalDataInPeriod = - this.environmentalData.mapValues { entry -> - entry - .value - .takePeriod(dateTimeFrom, dateTimeTo) - .map { it.second } - } + val environmentalDataInPeriod = this.environmentalData.mapValues { roomDataEntry -> roomDataEntry + .value + .takePeriod(dateTimeFrom, dateTimeTo) + .map { it.second } + } Pair( - it.second, + stateEntry.second, SurgeryProcessStepAggregateData( - it.first, - AggregateData( - average = vitalSignsInPeriod.applyAggregationToVitalSigns { this.average() }, - variance = vitalSignsInPeriod.applyAggregationToVitalSigns { this.variance() }, - maximum = vitalSignsInPeriod.applyAggregationToVitalSigns { this.max() }, - minimum = vitalSignsInPeriod.applyAggregationToVitalSigns { this.min() }, - ), + stateEntry.first, + AggregateVitalSignsExtractor(vitalSignsInPeriod).aggregate(), environmentalDataInPeriod.mapValues { roomDataEntry -> - with(roomDataEntry.value) { - AggregateData( - average = this.applyAggregationToRoomEnvironmentalData { this.average() }, - variance = this.applyAggregationToRoomEnvironmentalData { this.variance() }, - maximum = this.applyAggregationToRoomEnvironmentalData { this.max() }, - minimum = this.applyAggregationToRoomEnvironmentalData { this.min() }, - ) - } + AggregateRoomEnvironmentalDataExtractor(roomDataEntry.value).aggregate() }, ), ) } } - - private fun Collection.applyAggregationToRoomEnvironmentalData( - operation: Collection.() -> Double, - ): RoomEnvironmentalData = RoomEnvironmentalData( - temperature = Temperature( - this.mapNotNull { it.temperature?.value }.operation(), - TemperatureUnit.CELSIUS, - ), - humidity = Humidity(Percentage(this.mapNotNull { it.humidity?.percentage?.value }.operation())), - luminosity = Luminosity( - this.mapNotNull { it.luminosity?.value }.operation(), - LightUnit.LUX, - ), - presence = Presence( - this.mapNotNull { it.presence?.presenceDetected }.groupBy { it }.maxBy { it.value.size }.key, - ), - ) - - private fun Collection.applyAggregationToVitalSigns( - operation: Collection.() -> Double, - ): PatientVitalSigns = PatientVitalSigns( - heartBeat = VitalSign.HeartBeat(this.mapNotNull { it.heartBeat?.bpm?.toDouble() }.operation().toInt()), - diastolicBloodPressure = VitalSign.DiastolicBloodPressure( - this.mapNotNull { it.diastolicBloodPressure?.pressure?.toDouble() }.operation().toInt(), - ), - systolicBloodPressure = VitalSign.SystolicBloodPressure( - this.mapNotNull { it.systolicBloodPressure?.pressure?.toDouble() }.operation().toInt(), - ), - respiratoryRate = VitalSign.RespiratoryRate( - this.mapNotNull { it.respiratoryRate?.rate?.toDouble() }.operation().toInt(), - ), - saturationPercentage = VitalSign.SaturationPercentage( - Percentage(this.mapNotNull { it.saturationPercentage?.percentage?.value }.operation()), - ), - bodyTemperature = VitalSign.BodyTemperature( - Temperature(this.mapNotNull { it.bodyTemperature?.temperature?.value }.average(), TemperatureUnit.CELSIUS), - ), - ) - private fun Collection>.takePeriod(from: Instant, to: Instant? = null) = - this.filter { - (to != null && it.first >= from && it.first <= to) || (to == null && it.first >= from) - } - private fun Collection.variance(): Double = with(this.average()) { - this@variance.sumOf { (it - this).pow(2) } / this@variance.size - } }