diff --git a/CHANGELOG.md b/CHANGELOG.md index b6362dc295e..99ab4d12a33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ - Add `cholesterol_value` to `MedicalHistory` table - Bump AGP to v8.8.1 - Fix JSON variable name in non-lab based statin calculation sheet +- Add `LabBasedCVDRiskCalculator` and effect to calculate lab based cvd risk. ### Fixes diff --git a/app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskCalculationSheet.kt b/app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskCalculationSheet.kt index 65e3500230f..37b01d7b2de 100644 --- a/app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskCalculationSheet.kt +++ b/app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskCalculationSheet.kt @@ -2,11 +2,12 @@ package org.simple.clinic.cvdrisk import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.simple.clinic.medicalhistory.Answer @JsonClass(generateAdapter = true) data class LabBasedCVDRiskCalculationSheet( val diabetes: DiabetesRisk, - @Json(name = "nodiabetes") val noDiabetes: NoDiabetesRisk, + @Json(name = "nodiabetes") val noDiabetes: DiabetesRisk, ) : CVDRiskCalculationSheet { @JsonClass(generateAdapter = true) @@ -14,39 +15,41 @@ data class LabBasedCVDRiskCalculationSheet( val women: Women, val men: Men ) - - @JsonClass(generateAdapter = true) - data class NoDiabetesRisk( - val women: Women, - val men: Men - ) } @JsonClass(generateAdapter = true) data class NonLabBasedCVDRiskCalculationSheet( val women: Women, val men: Men -): CVDRiskCalculationSheet +) : CVDRiskCalculationSheet sealed interface CVDRiskCalculationSheet @JsonClass(generateAdapter = true) -data class Women( +data class Women( override val smoking: AgeData, @Json(name = "nonsmoking") override val nonSmoking: AgeData -): SmokingData +) : SmokingData @JsonClass(generateAdapter = true) -data class Men( +data class Men( override val smoking: AgeData, @Json(name = "nonsmoking") override val nonSmoking: AgeData -): SmokingData +) : SmokingData -sealed interface SmokingData { +sealed interface SmokingData { val smoking: AgeData val nonSmoking: AgeData + + fun ageDataForSmokingStatus(isSmoker: Answer): List> { + return when (isSmoker) { + Answer.Yes -> listOf(smoking) + Answer.No -> listOf(nonSmoking) + else -> listOf(nonSmoking, smoking) + } + } } @JsonClass(generateAdapter = true) @@ -58,20 +61,47 @@ data class AgeData( @Json(name = "60 - 64") val age60to64: List, @Json(name = "65 - 69") val age65to69: List, @Json(name = "70 - 74") val age70to74: List -) +) { + + fun riskForAge(age: Int): List { + return when (age) { + in 40..44 -> age40to44 + in 45..49 -> age45to49 + in 50..54 -> age50to54 + in 55..59 -> age55to59 + in 60..64 -> age60to64 + in 65..69 -> age65to69 + in 70..74 -> age70to74 + else -> emptyList() + } + } +} @JsonClass(generateAdapter = true) data class LabBasedRiskEntry( - @Json(name = "sbp") val systolic: String, + @Json(name = "sbp") override val systolic: String, @Json(name = "chol") val cholesterol: String, val risk: Int ) : RiskEntry @JsonClass(generateAdapter = true) data class NonLabBasedRiskEntry( - @Json(name = "sbp") val systolic: String, + @Json(name = "sbp") override val systolic: String, val bmi: String, val risk: Int ) : RiskEntry -sealed interface RiskEntry +sealed interface RiskEntry { + + val systolic: String + + fun isInSystolicRange(systolic: Int): Boolean { + val systolicRange = when (systolic) { + in 0..159 -> "140 - 159" + in 160..179 -> "160 - 179" + else -> ">= 180" + } + + return this.systolic == systolicRange + } +} diff --git a/app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskCalculator.kt b/app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskCalculator.kt deleted file mode 100644 index 279137c6389..00000000000 --- a/app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskCalculator.kt +++ /dev/null @@ -1,91 +0,0 @@ -package org.simple.clinic.cvdrisk - -import dagger.Lazy -import org.simple.clinic.di.AppScope -import org.simple.clinic.medicalhistory.Answer -import org.simple.clinic.patient.Gender -import javax.inject.Inject - -@AppScope -class CVDRiskCalculator @Inject constructor( - private val nonLabBasedCVDRiskCalculationSheet: Lazy, -) { - fun calculateCvdRisk(cvdRiskInput: CVDRiskInput): CVDRiskRange? { - with(cvdRiskInput) { - val riskEntries = getNonLabBasedRiskEntries(cvdRiskInput) ?: return null - - val systolicRange = getSystolicRange(systolic) - val bmiRangeList = getBMIRangeList(bmi) - val risks = riskEntries.filter { it.systolic == systolicRange && it.bmi in bmiRangeList }.map { it.risk } - return formatRisk(risks) - } - } - - private fun getNonLabBasedRiskEntries(cvdRiskInput: CVDRiskInput): List? { - with(cvdRiskInput) { - val sheet = nonLabBasedCVDRiskCalculationSheet.get() ?: return null - val genderData = getGenderData(sheet, gender) - val smokingDataList = genderData?.let { getSmokingDataList(it, isSmoker) } - return smokingDataList?.let { getAgeRange(smokingDataList, age) } - } - } - - private fun getGenderData(cvdRiskData: NonLabBasedCVDRiskCalculationSheet, gender: Gender) = when (gender) { - Gender.Female -> cvdRiskData.women - Gender.Male -> cvdRiskData.men - else -> null - } - - private fun getSmokingDataList(smokingData: SmokingData, isSmoker: Answer) = when (isSmoker) { - Answer.Yes -> listOf(smokingData.smoking) - Answer.No -> listOf(smokingData.nonSmoking) - else -> listOf(smokingData.nonSmoking, smokingData.smoking) - } - - private fun getAgeRange(ageData: List>, age: Int): List? { - val ageToRiskMapping = mapOf( - 40..44 to { data: AgeData -> data.age40to44 }, - 45..49 to { data: AgeData -> data.age45to49 }, - 50..54 to { data: AgeData -> data.age50to54 }, - 55..59 to { data: AgeData -> data.age55to59 }, - 60..64 to { data: AgeData -> data.age60to64 }, - 65..69 to { data: AgeData -> data.age65to69 }, - 70..74 to { data: AgeData -> data.age70to74 } - ) - - val riskExtractor = ageToRiskMapping.entries - .firstOrNull { age in it.key } - ?.value ?: return null - - return ageData.map(riskExtractor).flatten() - } - - private fun getSystolicRange(sbp: Int) = when (sbp) { - in 0..159 -> "140 - 159" - in 160..179 -> "160 - 179" - else -> ">= 180" - } - - private fun getBMIRangeList(bmi: Float?): List { - return bmi?.let { listOf(getBMIRange(it)) } - ?: listOf("< 20", "20 - 24", "25 - 29", "30 - 35", "> 35") - } - - private fun getBMIRange(bmi: Float): String { - return when (bmi) { - in 0.0..19.9 -> "< 20" - in 20.0..24.9 -> "20 - 24" - in 25.0..29.9 -> "25 - 29" - in 30.0..34.9 -> "30 - 35" - else -> "> 35" - } - } - - private fun formatRisk(risks: List): CVDRiskRange? { - return when { - risks.isEmpty() -> null - risks.size == 1 -> CVDRiskRange(risks.first(), risks.first()) - else -> CVDRiskRange(risks.min(), risks.max()) - } - } -} diff --git a/app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskRange.kt b/app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskRange.kt index 6be8d14f045..f0056124622 100644 --- a/app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskRange.kt +++ b/app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskRange.kt @@ -37,6 +37,15 @@ data class CVDRiskRange( } companion object { + + fun from(risks: List): CVDRiskRange? { + return when { + risks.isEmpty() -> null + risks.size == 1 -> CVDRiskRange(min = risks.first(), max = risks.first()) + else -> CVDRiskRange(risks.min(), risks.max()) + } + } + fun parseRiskRange(risk: String): CVDRiskRange { val risks = risk.split("-").map { it.trim() } return when (risks.size) { diff --git a/app/src/main/java/org/simple/clinic/cvdrisk/LabBasedCVDRiskInput.kt b/app/src/main/java/org/simple/clinic/cvdrisk/LabBasedCVDRiskInput.kt new file mode 100644 index 00000000000..9a2a77a69e3 --- /dev/null +++ b/app/src/main/java/org/simple/clinic/cvdrisk/LabBasedCVDRiskInput.kt @@ -0,0 +1,13 @@ +package org.simple.clinic.cvdrisk + +import org.simple.clinic.medicalhistory.Answer +import org.simple.clinic.patient.Gender + +data class LabBasedCVDRiskInput( + val gender: Gender, + val age: Int, + val systolic: Int, + val isSmoker: Answer = Answer.Unanswered, + val diagnosedWithDiabetes: Answer = Answer.Unanswered, + val cholesterol: Float? = null, +) diff --git a/app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskInput.kt b/app/src/main/java/org/simple/clinic/cvdrisk/NonLabBasedCVDRiskInput.kt similarity index 78% rename from app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskInput.kt rename to app/src/main/java/org/simple/clinic/cvdrisk/NonLabBasedCVDRiskInput.kt index f2a03a481ee..d1a62f0d850 100644 --- a/app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskInput.kt +++ b/app/src/main/java/org/simple/clinic/cvdrisk/NonLabBasedCVDRiskInput.kt @@ -3,10 +3,11 @@ package org.simple.clinic.cvdrisk import org.simple.clinic.medicalhistory.Answer import org.simple.clinic.patient.Gender -data class CVDRiskInput( +data class NonLabBasedCVDRiskInput( val gender: Gender, val age: Int, val systolic: Int, val isSmoker: Answer = Answer.Unanswered, - val bmi: Float? = null + val bmi: Float? = null, ) + diff --git a/app/src/main/java/org/simple/clinic/cvdrisk/calculator/LabBasedCVDRiskCalculator.kt b/app/src/main/java/org/simple/clinic/cvdrisk/calculator/LabBasedCVDRiskCalculator.kt new file mode 100644 index 00000000000..244229e49dc --- /dev/null +++ b/app/src/main/java/org/simple/clinic/cvdrisk/calculator/LabBasedCVDRiskCalculator.kt @@ -0,0 +1,71 @@ +package org.simple.clinic.cvdrisk.calculator + +import dagger.Lazy +import org.simple.clinic.cvdrisk.CVDRiskRange +import org.simple.clinic.cvdrisk.LabBasedCVDRiskCalculationSheet +import org.simple.clinic.cvdrisk.LabBasedCVDRiskInput +import org.simple.clinic.cvdrisk.LabBasedRiskEntry +import org.simple.clinic.di.AppScope +import org.simple.clinic.medicalhistory.Answer +import org.simple.clinic.patient.Gender +import javax.inject.Inject + +@AppScope +class LabBasedCVDRiskCalculator @Inject constructor( + private val labBasedCVDRiskCalculationSheet: Lazy, +) { + + fun calculateCvdRisk(cvdRiskInput: LabBasedCVDRiskInput): CVDRiskRange? { + with(cvdRiskInput) { + val riskEntries = getLabBasedRiskEntries(cvdRiskInput) ?: return null + val cholesterolRangeList = getCholesterolRangeList(cholesterol) + val risks = + riskEntries + .filter { it.isInSystolicRange(systolic) && it.cholesterol in cholesterolRangeList } + .map { it.risk } + + return CVDRiskRange.from(risks) + } + } + + private fun getLabBasedRiskEntries(cvdRiskInput: LabBasedCVDRiskInput): List? { + with(cvdRiskInput) { + val sheet = labBasedCVDRiskCalculationSheet.get() + val diabetesData = sheet?.let { getDiabetesData(it, diagnosedWithDiabetes) } + val genderData = diabetesData?.let { getGenderData(it, gender) } + val smokingDataList = genderData?.ageDataForSmokingStatus(isSmoker) + + return smokingDataList?.flatMap { it.riskForAge(age) } + } + } + + private fun getGenderData(genderData: LabBasedCVDRiskCalculationSheet.DiabetesRisk, gender: Gender) = when (gender) { + Gender.Female -> genderData.women + Gender.Male -> genderData.men + else -> null + } + + private fun getDiabetesData(diabetesData: LabBasedCVDRiskCalculationSheet, answer: Answer) = + when (answer) { + Answer.Yes -> diabetesData.diabetes + Answer.No -> diabetesData.noDiabetes + else -> null + } + + + private fun getCholesterolRangeList(cholesterol: Float?): List { + return cholesterol?.let { listOf(getCholesterolRange(it)) } + ?: listOf("< 4", "4 - 4.9", "5 - 5.9", "6 - 6.9", ">= 7") + } + + private fun getCholesterolRange(cholesterol: Float): String { + return when { + cholesterol >= 0.0 && cholesterol < 4.0 -> "< 4" + cholesterol >= 4.0 && cholesterol < 5.0 -> "4 - 4.9" + cholesterol >= 5.0 && cholesterol < 6.0 -> "5 - 5.9" + cholesterol >= 6.0 && cholesterol < 7.0 -> "6 - 6.9" + else -> ">= 7" + } + } + +} diff --git a/app/src/main/java/org/simple/clinic/cvdrisk/calculator/NonLabBasedCVDRiskCalculator.kt b/app/src/main/java/org/simple/clinic/cvdrisk/calculator/NonLabBasedCVDRiskCalculator.kt new file mode 100644 index 00000000000..6006b93b315 --- /dev/null +++ b/app/src/main/java/org/simple/clinic/cvdrisk/calculator/NonLabBasedCVDRiskCalculator.kt @@ -0,0 +1,58 @@ +package org.simple.clinic.cvdrisk.calculator + +import dagger.Lazy +import org.simple.clinic.cvdrisk.CVDRiskRange +import org.simple.clinic.cvdrisk.NonLabBasedCVDRiskCalculationSheet +import org.simple.clinic.cvdrisk.NonLabBasedCVDRiskInput +import org.simple.clinic.cvdrisk.NonLabBasedRiskEntry +import org.simple.clinic.di.AppScope +import org.simple.clinic.patient.Gender +import javax.inject.Inject + +@AppScope +class NonLabBasedCVDRiskCalculator @Inject constructor( + private val nonLabBasedCVDRiskCalculationSheet: Lazy, +) { + fun calculateCvdRisk(cvdRiskInput: NonLabBasedCVDRiskInput): CVDRiskRange? { + with(cvdRiskInput) { + val riskEntries = getNonLabBasedRiskEntries(cvdRiskInput) ?: return null + val bmiRangeList = getBMIRangeList(bmi) + val risks = riskEntries + .filter { it.isInSystolicRange(systolic) && it.bmi in bmiRangeList } + .map { it.risk } + + return CVDRiskRange.from(risks) + } + } + + private fun getNonLabBasedRiskEntries(cvdRiskInput: NonLabBasedCVDRiskInput): List? { + with(cvdRiskInput) { + val sheet = nonLabBasedCVDRiskCalculationSheet.get() + val genderData = sheet?.let { getGenderData(it, gender) } + val smokingDataList = genderData?.ageDataForSmokingStatus(isSmoker) + + return smokingDataList?.flatMap { it.riskForAge(age) } + } + } + + private fun getGenderData(genderData: NonLabBasedCVDRiskCalculationSheet, gender: Gender) = when (gender) { + Gender.Female -> genderData.women + Gender.Male -> genderData.men + else -> null + } + + private fun getBMIRangeList(bmi: Float?): List { + return bmi?.let { listOf(getBMIRange(it)) } + ?: listOf("< 20", "20 - 24", "25 - 29", "30 - 35", "> 35") + } + + private fun getBMIRange(bmi: Float): String { + return when (bmi) { + in 0.0..19.9 -> "< 20" + in 20.0..24.9 -> "20 - 24" + in 25.0..29.9 -> "25 - 29" + in 30.0..34.9 -> "30 - 35" + else -> "> 35" + } + } +} diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffect.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffect.kt index a4822cd4dc8..7f1f9dbd95a 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffect.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffect.kt @@ -63,6 +63,8 @@ data class LoadStatinPrescriptionCheckInfo(val patient: Patient) : PatientSummar data class CalculateNonLabBasedCVDRisk(val patient: Patient) : PatientSummaryEffect() +data class CalculateLabBasedCVDRisk(val patient: Patient) : PatientSummaryEffect() + data class SaveCVDRisk( val patientUuid: UUID, val cvdRiskRange: CVDRiskRange diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt index 8097fb61fe8..e5cc820d4f8 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt @@ -12,11 +12,13 @@ import io.reactivex.Scheduler import org.simple.clinic.appconfig.Country import org.simple.clinic.bloodsugar.BloodSugarRepository import org.simple.clinic.bp.BloodPressureRepository -import org.simple.clinic.cvdrisk.CVDRiskCalculator -import org.simple.clinic.cvdrisk.CVDRiskInput import org.simple.clinic.cvdrisk.CVDRiskRange import org.simple.clinic.cvdrisk.CVDRiskRepository +import org.simple.clinic.cvdrisk.LabBasedCVDRiskInput +import org.simple.clinic.cvdrisk.NonLabBasedCVDRiskInput import org.simple.clinic.cvdrisk.StatinInfo +import org.simple.clinic.cvdrisk.calculator.LabBasedCVDRiskCalculator +import org.simple.clinic.cvdrisk.calculator.NonLabBasedCVDRiskCalculator import org.simple.clinic.drugs.DiagnosisWarningPrescriptions import org.simple.clinic.drugs.PrescriptionRepository import org.simple.clinic.facility.Facility @@ -71,7 +73,8 @@ class PatientSummaryEffectHandler @AssistedInject constructor( private val prescriptionRepository: PrescriptionRepository, private val cdssPilotFacilities: Lazy>, private val diagnosisWarningPrescriptions: Provider, - private val cvdRiskCalculator: CVDRiskCalculator, + private val nonLabBasedCVDRiskCalculator: NonLabBasedCVDRiskCalculator, + private val labBasedCVDRiskCalculator: LabBasedCVDRiskCalculator, @Assisted private val viewEffectsConsumer: Consumer ) { @@ -105,6 +108,7 @@ class PatientSummaryEffectHandler @AssistedInject constructor( .addConsumer(MarkHypertensionDiagnosis::class.java, { markHypertension(it.patientUuid) }, schedulersProvider.io()) .addTransformer(LoadStatinPrescriptionCheckInfo::class.java, loadStatinPrescriptionCheckInfo()) .addTransformer(CalculateNonLabBasedCVDRisk::class.java, calculateNonLabBasedCVDRisk()) + .addTransformer(CalculateLabBasedCVDRisk::class.java, calculateLabBasedCVDRisk()) .addTransformer(UpdateCVDRisk::class.java, updateCVDRisk()) .addTransformer(SaveCVDRisk::class.java, saveCVDRisk()) .addTransformer(LoadStatinInfo::class.java, loadStatinInfo()) @@ -188,8 +192,8 @@ class PatientSummaryEffectHandler @AssistedInject constructor( var risk: CVDRiskRange? = null if (bloodPressure != null) { - risk = cvdRiskCalculator.calculateCvdRisk( - CVDRiskInput( + risk = nonLabBasedCVDRiskCalculator.calculateCvdRisk( + NonLabBasedCVDRiskInput( gender = patient.gender, age = patient.ageDetails.estimateAge(userClock), systolic = bloodPressure.reading.systolic, @@ -205,6 +209,41 @@ class PatientSummaryEffectHandler @AssistedInject constructor( } } + private fun calculateLabBasedCVDRisk(): ObservableTransformer { + return ObservableTransformer { effects -> + effects + .observeOn(schedulersProvider.io()) + .map { effect -> + val patient = effect.patient + val bloodPressure = bloodPressureRepository + .newestMeasurementsForPatientImmediate(patient.uuid, 1).firstOrNull() + + val medicalHistory = medicalHistoryRepository.historyForPatientOrDefaultImmediate( + defaultHistoryUuid = uuidGenerator.v4(), + patientUuid = patient.uuid + ) + + var risk: CVDRiskRange? = null + + if (bloodPressure != null) { + risk = labBasedCVDRiskCalculator.calculateCvdRisk( + LabBasedCVDRiskInput( + gender = patient.gender, + age = patient.ageDetails.estimateAge(userClock), + systolic = bloodPressure.reading.systolic, + isSmoker = medicalHistory.isSmoking, + diagnosedWithDiabetes = medicalHistory.diagnosedWithDiabetes, + cholesterol = null //Update once the value is available in medical history + ) + ) + } + + val existingCvdRisk = cvdRiskRepository.getCVDRiskImmediate(patient.uuid) + CVDRiskCalculated(existingCvdRisk, risk) + } + } + } + private fun updateCVDRisk(): ObservableTransformer { return ObservableTransformer { effects -> effects diff --git a/app/src/test/java/org/simple/clinic/cvdrisk/LabBasedCVDRiskCalculatorTest.kt b/app/src/test/java/org/simple/clinic/cvdrisk/LabBasedCVDRiskCalculatorTest.kt new file mode 100644 index 00000000000..025593530e5 --- /dev/null +++ b/app/src/test/java/org/simple/clinic/cvdrisk/LabBasedCVDRiskCalculatorTest.kt @@ -0,0 +1,108 @@ +package org.simple.clinic.cvdrisk + +import org.junit.Assert.assertEquals +import org.junit.Test +import org.simple.clinic.TestData +import org.simple.clinic.cvdrisk.calculator.LabBasedCVDRiskCalculator +import org.simple.clinic.medicalhistory.Answer +import org.simple.clinic.patient.Gender + +class LabBasedCVDRiskCalculatorTest { + + private val labBasedCVDRiskCalculationSheet = TestData.labBasedCVDRiskCalculationSheet() + private val cvdRiskCalculator = LabBasedCVDRiskCalculator( + labBasedCVDRiskCalculationSheet = { labBasedCVDRiskCalculationSheet } + ) + + @Test + fun `should return exact risk for matching data`() { + val expectedRiskRange = CVDRiskRange(7, 7) + val cvdRiskInput = LabBasedCVDRiskInput( + gender = Gender.Female, + age = 40, + systolic = 130, + isSmoker = Answer.Yes, + diagnosedWithDiabetes = Answer.Yes, + cholesterol = 3f + ) + val riskRange = cvdRiskCalculator.calculateCvdRisk(cvdRiskInput) + + assertEquals(expectedRiskRange, riskRange) + } + + @Test + fun `should return risk range when cholesterol is not specified`() { + val expectedRiskRange = CVDRiskRange(7, 13) + val cvdRiskInput = LabBasedCVDRiskInput( + gender = Gender.Female, + age = 40, + systolic = 130, + isSmoker = Answer.Yes, + diagnosedWithDiabetes = Answer.Yes, + ) + val riskRange = cvdRiskCalculator.calculateCvdRisk(cvdRiskInput) + + assertEquals(expectedRiskRange, riskRange) + } + + @Test + fun `should return null when no matching data`() { + val cvdRiskInput = LabBasedCVDRiskInput( + gender = Gender.Male, + age = 80, + systolic = 200, + isSmoker = Answer.Yes, + cholesterol = 5.9f, + diagnosedWithDiabetes = Answer.Yes, + ) + val riskRange = cvdRiskCalculator.calculateCvdRisk(cvdRiskInput) + + assertEquals(null, riskRange) + } + + @Test + fun `should handle nonsmoking data correctly`() { + val expectedRiskRange = CVDRiskRange(4, 4) + val cvdRiskInput = LabBasedCVDRiskInput( + gender = Gender.Male, + age = 40, + systolic = 125, + isSmoker = Answer.No, + cholesterol = 5.9f, + diagnosedWithDiabetes = Answer.Yes, + ) + val riskRange = cvdRiskCalculator.calculateCvdRisk(cvdRiskInput) + + assertEquals(expectedRiskRange, riskRange) + } + + @Test + fun `should return risk range when smoking is unanswered`() { + val expectedRiskRange = CVDRiskRange(4, 7) + val cvdRiskInput = LabBasedCVDRiskInput( + gender = Gender.Male, + age = 40, + systolic = 125, + isSmoker = Answer.Unanswered, + cholesterol = 3.4f, + diagnosedWithDiabetes = Answer.Yes, + ) + val riskRange = cvdRiskCalculator.calculateCvdRisk(cvdRiskInput) + + assertEquals(expectedRiskRange, riskRange) + } + + @Test + fun `should return risk range when cholesterol and smoking is not specified`() { + val expectedRiskRange = CVDRiskRange(4, 14) + val cvdRiskInput = LabBasedCVDRiskInput( + gender = Gender.Male, + age = 40, + systolic = 125, + diagnosedWithDiabetes = Answer.Yes, + ) + val riskRange = cvdRiskCalculator.calculateCvdRisk(cvdRiskInput) + + assertEquals(expectedRiskRange, riskRange) + } +} diff --git a/app/src/test/java/org/simple/clinic/cvdrisk/CVDRiskCalculatorTest.kt b/app/src/test/java/org/simple/clinic/cvdrisk/NonLabBasedCVDRiskCalculatorTest.kt similarity index 82% rename from app/src/test/java/org/simple/clinic/cvdrisk/CVDRiskCalculatorTest.kt rename to app/src/test/java/org/simple/clinic/cvdrisk/NonLabBasedCVDRiskCalculatorTest.kt index 692b3035569..8fbcbf66fe0 100644 --- a/app/src/test/java/org/simple/clinic/cvdrisk/CVDRiskCalculatorTest.kt +++ b/app/src/test/java/org/simple/clinic/cvdrisk/NonLabBasedCVDRiskCalculatorTest.kt @@ -3,19 +3,20 @@ package org.simple.clinic.cvdrisk import org.junit.Assert.assertEquals import org.junit.Test import org.simple.clinic.TestData +import org.simple.clinic.cvdrisk.calculator.NonLabBasedCVDRiskCalculator import org.simple.clinic.medicalhistory.Answer import org.simple.clinic.patient.Gender -class CVDRiskCalculatorTest { +class NonLabBasedCVDRiskCalculatorTest { private val nonLabBasedCVDRiskCalculationSheet = TestData.nonLabBasedCVDRiskCalculationSheet() - private val cvdRiskCalculator = CVDRiskCalculator( + private val cvdRiskCalculator = NonLabBasedCVDRiskCalculator( nonLabBasedCVDRiskCalculationSheet = { nonLabBasedCVDRiskCalculationSheet } ) @Test fun `should return exact risk for matching data`() { - val cvdRiskInput = CVDRiskInput( + val cvdRiskInput = NonLabBasedCVDRiskInput( gender = Gender.Female, age = 40, systolic = 130, @@ -29,7 +30,7 @@ class CVDRiskCalculatorTest { @Test fun `should return risk range when bmi is not specified`() { - val cvdRiskInput = CVDRiskInput( + val cvdRiskInput = NonLabBasedCVDRiskInput( gender = Gender.Female, age = 40, systolic = 130, @@ -42,7 +43,7 @@ class CVDRiskCalculatorTest { @Test fun `should return null when no matching data`() { - val cvdRiskInput = CVDRiskInput( + val cvdRiskInput = NonLabBasedCVDRiskInput( gender = Gender.Male, age = 80, systolic = 200, @@ -55,7 +56,7 @@ class CVDRiskCalculatorTest { @Test fun `should handle nonsmoking data correctly`() { - val cvdRiskInput = CVDRiskInput( + val cvdRiskInput = NonLabBasedCVDRiskInput( gender = Gender.Male, age = 40, systolic = 125, @@ -68,7 +69,7 @@ class CVDRiskCalculatorTest { @Test fun `should return risk range when smoking is unanswered`() { - val cvdRiskInput = CVDRiskInput( + val cvdRiskInput = NonLabBasedCVDRiskInput( gender = Gender.Male, age = 40, systolic = 125, @@ -81,7 +82,7 @@ class CVDRiskCalculatorTest { @Test fun `should return risk range when bmi and smoking is not specified`() { - val cvdRiskInput = CVDRiskInput( + val cvdRiskInput = NonLabBasedCVDRiskInput( gender = Gender.Male, age = 40, systolic = 125, diff --git a/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt b/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt index b0c5cfaad09..e878381d883 100644 --- a/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt @@ -13,10 +13,11 @@ import org.mockito.kotlin.whenever import org.simple.clinic.TestData import org.simple.clinic.bloodsugar.BloodSugarRepository import org.simple.clinic.bp.BloodPressureRepository -import org.simple.clinic.cvdrisk.CVDRiskCalculator +import org.simple.clinic.cvdrisk.calculator.NonLabBasedCVDRiskCalculator import org.simple.clinic.cvdrisk.CVDRiskRange import org.simple.clinic.cvdrisk.CVDRiskRepository import org.simple.clinic.cvdrisk.StatinInfo +import org.simple.clinic.cvdrisk.calculator.LabBasedCVDRiskCalculator import org.simple.clinic.drugs.DiagnosisWarningPrescriptions import org.simple.clinic.drugs.PrescriptionRepository import org.simple.clinic.facility.FacilityRepository @@ -79,7 +80,8 @@ class PatientSummaryEffectHandlerTest { htnPrescriptions = listOf("amlodipine"), diabetesPrescriptions = listOf("metformin") ) - private val cvdRiskCalculator = CVDRiskCalculator { TestData.nonLabBasedCVDRiskCalculationSheet() } + private val nonLabBasedCVDRiskCalculator = NonLabBasedCVDRiskCalculator { TestData.nonLabBasedCVDRiskCalculationSheet() } + private val labBasedCVDRiskCalculator = LabBasedCVDRiskCalculator { TestData.labBasedCVDRiskCalculationSheet() } private val effectHandler = PatientSummaryEffectHandler( clock = clock, @@ -92,6 +94,8 @@ class PatientSummaryEffectHandlerTest { bloodSugarRepository = bloodSugarRepository, dataSync = dataSync, medicalHistoryRepository = medicalHistoryRepository, + cvdRiskRepository = cvdRiskRepository, + patientAttributeRepository = patientAttributeRepository, country = TestData.country(), currentUser = { user }, currentFacility = { facility }, @@ -101,10 +105,9 @@ class PatientSummaryEffectHandlerTest { prescriptionRepository = prescriptionRepository, cdssPilotFacilities = { emptyList() }, diagnosisWarningPrescriptions = { diagnosisWarningPrescriptions }, - cvdRiskRepository = cvdRiskRepository, + nonLabBasedCVDRiskCalculator = nonLabBasedCVDRiskCalculator, + labBasedCVDRiskCalculator = labBasedCVDRiskCalculator, viewEffectsConsumer = viewEffectHandler::handle, - cvdRiskCalculator = cvdRiskCalculator, - patientAttributeRepository = patientAttributeRepository, ) private val testCase = EffectHandlerTestCase(effectHandler.build()) @@ -138,6 +141,8 @@ class PatientSummaryEffectHandlerTest { bloodSugarRepository = bloodSugarRepository, dataSync = dataSync, medicalHistoryRepository = medicalHistoryRepository, + cvdRiskRepository = cvdRiskRepository, + patientAttributeRepository = patientAttributeRepository, country = bangladesh, currentUser = { user }, currentFacility = { facility }, @@ -146,11 +151,10 @@ class PatientSummaryEffectHandlerTest { teleconsultationFacilityRepository = teleconsultFacilityRepository, prescriptionRepository = prescriptionRepository, cdssPilotFacilities = { emptyList() }, - viewEffectsConsumer = viewEffectHandler::handle, diagnosisWarningPrescriptions = { diagnosisWarningPrescriptions }, - cvdRiskRepository = cvdRiskRepository, - cvdRiskCalculator = cvdRiskCalculator, - patientAttributeRepository = patientAttributeRepository, + nonLabBasedCVDRiskCalculator = nonLabBasedCVDRiskCalculator, + labBasedCVDRiskCalculator = labBasedCVDRiskCalculator, + viewEffectsConsumer = viewEffectHandler::handle, ) val testCase = EffectHandlerTestCase(effectHandler.build()) val registeredFacilityUuid = UUID.fromString("1b359ec9-02e2-4f50-bebd-6001f96df57f") @@ -201,6 +205,8 @@ class PatientSummaryEffectHandlerTest { bloodSugarRepository = bloodSugarRepository, dataSync = dataSync, medicalHistoryRepository = medicalHistoryRepository, + cvdRiskRepository = cvdRiskRepository, + patientAttributeRepository = patientAttributeRepository, country = bangladesh, currentUser = { user }, currentFacility = { facility }, @@ -210,10 +216,9 @@ class PatientSummaryEffectHandlerTest { prescriptionRepository = prescriptionRepository, cdssPilotFacilities = { emptyList() }, diagnosisWarningPrescriptions = { diagnosisWarningPrescriptions }, + nonLabBasedCVDRiskCalculator = nonLabBasedCVDRiskCalculator, + labBasedCVDRiskCalculator = labBasedCVDRiskCalculator, viewEffectsConsumer = viewEffectHandler::handle, - cvdRiskRepository = cvdRiskRepository, - cvdRiskCalculator = cvdRiskCalculator, - patientAttributeRepository = patientAttributeRepository, ) val testCase = EffectHandlerTestCase(effectHandler.build()) val patient = TestData.patient(patientUuid) @@ -633,6 +638,8 @@ class PatientSummaryEffectHandlerTest { bloodSugarRepository = bloodSugarRepository, dataSync = dataSync, medicalHistoryRepository = medicalHistoryRepository, + cvdRiskRepository = cvdRiskRepository, + patientAttributeRepository = patientAttributeRepository, country = TestData.country(), currentUser = { user }, currentFacility = { facility }, @@ -642,10 +649,9 @@ class PatientSummaryEffectHandlerTest { prescriptionRepository = prescriptionRepository, cdssPilotFacilities = { cdssPilotFacilities }, diagnosisWarningPrescriptions = { diagnosisWarningPrescriptions }, - cvdRiskRepository = cvdRiskRepository, + nonLabBasedCVDRiskCalculator = nonLabBasedCVDRiskCalculator, + labBasedCVDRiskCalculator = labBasedCVDRiskCalculator, viewEffectsConsumer = viewEffectHandler::handle, - cvdRiskCalculator = cvdRiskCalculator, - patientAttributeRepository = patientAttributeRepository, ) val testCase = EffectHandlerTestCase(effectHandler = effectHandler.build()) @@ -875,7 +881,7 @@ class PatientSummaryEffectHandlerTest { } @Test - fun `when calculate cvd risk effect is received, then calculate cvd risk`() { + fun `when calculate non lab based cvd risk effect is received, then calculate non lab based cvd risk`() { //given val patient = TestData.patient( uuid = patientUuid, @@ -906,7 +912,7 @@ class PatientSummaryEffectHandlerTest { patientUuid = patientUuid, )) doReturn null whenever(cvdRiskRepository.getCVDRiskImmediate(patientUuid)) doReturn - cvdRisk + cvdRisk //when testCase.dispatch(CalculateNonLabBasedCVDRisk(patient = patient)) @@ -915,6 +921,43 @@ class PatientSummaryEffectHandlerTest { testCase.assertOutgoingEvents(CVDRiskCalculated(cvdRisk, CVDRiskRange(6, 6))) } + @Test + fun `when calculate lab based cvd risk effect is received, then calculate lab based cvd risk`() { + //given + val patient = TestData.patient( + uuid = patientUuid, + gender = Gender.Male, + status = PatientStatus.Active, + patientAgeDetails = PatientAgeDetails( + ageValue = 40, + ageUpdatedAt = Instant.parse("2018-01-01T00:00:00Z"), + dateOfBirth = null, + ) + ) + val medicalHistory = TestData.medicalHistory(isSmoking = Yes) + val bloodPressure = TestData.bloodPressureMeasurement( + UUID.fromString("3e8c246f-91b9-4f8c-81fe-91b67ac0a2d5"), + systolic = 130, + patientUuid = patientUuid + ) + val bloodPressures = listOf(bloodPressure) + val cvdRisk = TestData.cvdRisk(riskScore = CVDRiskRange(27, 27)) + + whenever(bloodPressureRepository.newestMeasurementsForPatientImmediate(patientUuid = patientUuid, limit = 1)) doReturn bloodPressures + whenever(medicalHistoryRepository.historyForPatientOrDefaultImmediate( + patientUuid = patientUuid, + defaultHistoryUuid = uuidGenerator.v4() + )) doReturn medicalHistory + whenever(cvdRiskRepository.getCVDRiskImmediate(patientUuid)) doReturn + cvdRisk + + //when + testCase.dispatch(CalculateLabBasedCVDRisk(patient = patient)) + + //then + testCase.assertOutgoingEvents(CVDRiskCalculated(cvdRisk, CVDRiskRange(7, 14))) + } + @Test fun `when save cvd risk effect is received, then save the cvd risk`() { // when diff --git a/app/src/test/java/org/simple/clinic/summary/PatientSummaryScreenLogicTest.kt b/app/src/test/java/org/simple/clinic/summary/PatientSummaryScreenLogicTest.kt index 1db39fcc9e9..bcb810c8ad0 100644 --- a/app/src/test/java/org/simple/clinic/summary/PatientSummaryScreenLogicTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/PatientSummaryScreenLogicTest.kt @@ -15,10 +15,12 @@ import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.verify import org.mockito.kotlin.whenever +import org.simple.clinic.TestData import org.simple.clinic.bloodsugar.BloodSugarRepository import org.simple.clinic.bp.BloodPressureRepository -import org.simple.clinic.cvdrisk.CVDRiskCalculator import org.simple.clinic.cvdrisk.CVDRiskRepository +import org.simple.clinic.cvdrisk.calculator.LabBasedCVDRiskCalculator +import org.simple.clinic.cvdrisk.calculator.NonLabBasedCVDRiskCalculator import org.simple.clinic.drugs.DiagnosisWarningPrescriptions import org.simple.clinic.drugs.PrescriptionRepository import org.simple.clinic.facility.FacilityRepository @@ -34,14 +36,13 @@ import org.simple.clinic.patientattribute.PatientAttributeRepository import org.simple.clinic.summary.OpenIntention.LinkIdWithPatient import org.simple.clinic.summary.OpenIntention.ViewExistingPatient import org.simple.clinic.summary.OpenIntention.ViewNewPatient -import org.simple.clinic.util.scheduler.TestSchedulersProvider -import org.simple.clinic.widgets.UiEvent -import org.simple.mobius.migration.MobiusTestFixture -import org.simple.clinic.TestData import org.simple.clinic.util.RxErrorsRule import org.simple.clinic.util.TestUserClock import org.simple.clinic.util.TestUtcClock +import org.simple.clinic.util.scheduler.TestSchedulersProvider import org.simple.clinic.uuid.FakeUuidGenerator +import org.simple.clinic.widgets.UiEvent +import org.simple.mobius.migration.MobiusTestFixture import java.time.Duration import java.time.LocalDate import java.util.Optional @@ -221,6 +222,8 @@ class PatientSummaryScreenLogicTest { bloodSugarRepository = bloodSugarRepository, dataSync = mock(), medicalHistoryRepository = medicalHistoryRepository, + cvdRiskRepository = cvdRiskRepository, + patientAttributeRepository = patientAttributeRepository, country = TestData.country(), currentUser = { user }, currentFacility = { facility }, @@ -230,10 +233,9 @@ class PatientSummaryScreenLogicTest { prescriptionRepository = prescriptionRepository, cdssPilotFacilities = { emptyList() }, diagnosisWarningPrescriptions = { diagnosisWarningPrescriptions }, - viewEffectsConsumer = viewEffectHandler::handle, - cvdRiskRepository = cvdRiskRepository, - cvdRiskCalculator = CVDRiskCalculator { TestData.nonLabBasedCVDRiskCalculationSheet() }, - patientAttributeRepository = patientAttributeRepository + nonLabBasedCVDRiskCalculator = NonLabBasedCVDRiskCalculator { TestData.nonLabBasedCVDRiskCalculationSheet() }, + labBasedCVDRiskCalculator = LabBasedCVDRiskCalculator() { TestData.labBasedCVDRiskCalculationSheet() }, + viewEffectsConsumer = viewEffectHandler::handle ) testFixture = MobiusTestFixture( diff --git a/app/src/testFixtures/kotlin/org/simple/clinic/TestData.kt b/app/src/testFixtures/kotlin/org/simple/clinic/TestData.kt index e73c222c53b..1a6629978b8 100644 --- a/app/src/testFixtures/kotlin/org/simple/clinic/TestData.kt +++ b/app/src/testFixtures/kotlin/org/simple/clinic/TestData.kt @@ -13,9 +13,11 @@ import org.simple.clinic.bp.BloodPressureMeasurement import org.simple.clinic.bp.BloodPressureReading import org.simple.clinic.bp.sync.BloodPressureMeasurementPayload import org.simple.clinic.contactpatient.ContactPatientProfile +import org.simple.clinic.cvdrisk.AgeData import org.simple.clinic.cvdrisk.CVDRisk import org.simple.clinic.cvdrisk.CVDRiskRange -import org.simple.clinic.cvdrisk.AgeData +import org.simple.clinic.cvdrisk.LabBasedCVDRiskCalculationSheet +import org.simple.clinic.cvdrisk.LabBasedRiskEntry import org.simple.clinic.cvdrisk.Men import org.simple.clinic.cvdrisk.NonLabBasedCVDRiskCalculationSheet import org.simple.clinic.cvdrisk.NonLabBasedRiskEntry @@ -1836,4 +1838,152 @@ object TestData { men = menGenderData ) } + + fun labBasedCVDRiskCalculationSheet(): LabBasedCVDRiskCalculationSheet { + val smokingDataWomen = AgeData( + age40to44 = listOf( + LabBasedRiskEntry(systolic = ">= 180", cholesterol = "< 4", risk = 11), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "< 4", risk = 7), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "4 - 4.9", risk = 8), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "5 - 5.9", risk = 10), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "6 - 6.9", risk = 11), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = ">= 7", risk = 13), + ), + age45to49 = listOf( + LabBasedRiskEntry(systolic = ">= 180", cholesterol = "< 4", risk = 11), + LabBasedRiskEntry(systolic = "160 - 179", cholesterol = "4 - 4.9", risk = 9), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "5 - 5.9", risk = 5), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "6 - 6.9", risk = 6), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = ">= 7", risk = 6) + ), + age50to54 = listOf( + LabBasedRiskEntry(systolic = ">= 180", cholesterol = "< 4", risk = 11), + LabBasedRiskEntry(systolic = "160 - 179", cholesterol = "4 - 4.9", risk = 9), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "5 - 5.9", risk = 5), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "6 - 6.9", risk = 6), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = ">= 7", risk = 6) + ), + age55to59 = listOf( + LabBasedRiskEntry(systolic = ">= 180", cholesterol = "< 4", risk = 11), + LabBasedRiskEntry(systolic = "160 - 179", cholesterol = "4 - 4.9", risk = 9), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "5 - 5.9", risk = 5), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "6 - 6.9", risk = 6), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = ">= 7", risk = 6) + ), + age60to64 = listOf( + LabBasedRiskEntry(systolic = ">= 180", cholesterol = "< 4", risk = 11), + LabBasedRiskEntry(systolic = "160 - 179", cholesterol = "4 - 4.9", risk = 9), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "5 - 5.9", risk = 5), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "6 - 6.9", risk = 6), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = ">= 7", risk = 6) + ), + age65to69 = listOf( + LabBasedRiskEntry(systolic = ">= 180", cholesterol = "< 4", risk = 11), + LabBasedRiskEntry(systolic = "160 - 179", cholesterol = "4 - 4.9", risk = 9), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "5 - 5.9", risk = 5), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "6 - 6.9", risk = 6), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = ">= 7", risk = 6) + ), + age70to74 = listOf( + LabBasedRiskEntry(systolic = ">= 180", cholesterol = "< 4", risk = 11), + LabBasedRiskEntry(systolic = "160 - 179", cholesterol = "4 - 4.9", risk = 9), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "5 - 5.9", risk = 5), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "6 - 6.9", risk = 6), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = ">= 7", risk = 6) + ) + ) + + val nonSmokingDataWomen = AgeData( + age40to44 = listOf( + LabBasedRiskEntry(systolic = ">= 180", cholesterol = "< 4", risk = 5), + LabBasedRiskEntry(systolic = "160 - 179", cholesterol = "4 - 4.9", risk = 4), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "5 - 5.9", risk = 2), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "6 - 6.9", risk = 2), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = ">= 7", risk = 2) + ), + age45to49 = listOf( + LabBasedRiskEntry(systolic = ">= 180", cholesterol = "< 4", risk = 5), + LabBasedRiskEntry(systolic = "160 - 179", cholesterol = "4 - 4.9", risk = 4), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "5 - 5.9", risk = 2), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "6 - 6.9", risk = 2), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = ">= 7", risk = 2) + ), + age50to54 = listOf( + LabBasedRiskEntry(systolic = ">= 180", cholesterol = "< 4", risk = 5), + LabBasedRiskEntry(systolic = "160 - 179", cholesterol = "4 - 4.9", risk = 4), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "5 - 5.9", risk = 2), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "6 - 6.9", risk = 2), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = ">= 7", risk = 2) + ), + age55to59 = listOf( + LabBasedRiskEntry(systolic = ">= 180", cholesterol = "< 4", risk = 5), + LabBasedRiskEntry(systolic = "160 - 179", cholesterol = "4 - 4.9", risk = 4), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "5 - 5.9", risk = 2), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "6 - 6.9", risk = 2), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = ">= 7", risk = 2) + ), + age60to64 = listOf( + LabBasedRiskEntry(systolic = ">= 180", cholesterol = "< 4", risk = 5), + LabBasedRiskEntry(systolic = "160 - 179", cholesterol = "4 - 4.9", risk = 4), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "5 - 5.9", risk = 2), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "6 - 6.9", risk = 2), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = ">= 7", risk = 2) + ), + age65to69 = listOf( + LabBasedRiskEntry(systolic = ">= 180", cholesterol = "< 4", risk = 5), + LabBasedRiskEntry(systolic = "160 - 179", cholesterol = "4 - 4.9", risk = 4), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "5 - 5.9", risk = 2), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "6 - 6.9", risk = 2), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = ">= 7", risk = 2) + ), + age70to74 = listOf( + LabBasedRiskEntry(systolic = ">= 180", cholesterol = "< 4", risk = 5), + LabBasedRiskEntry(systolic = "160 - 179", cholesterol = "4 - 4.9", risk = 4), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "5 - 5.9", risk = 2), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = "6 - 6.9", risk = 2), + LabBasedRiskEntry(systolic = "120 - 139", cholesterol = ">= 7", risk = 2) + ) + ) + + val womenGenderData = Women( + smoking = smokingDataWomen, + nonSmoking = nonSmokingDataWomen + ) + + val smokingDataMen = smokingDataWomen.copy( + age40to44 = listOf( + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "< 4", risk = 7), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "4 - 4.9", risk = 8), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "5 - 5.9", risk = 9), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "6 - 6.9", risk = 11), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = ">= 7", risk = 14), + ) + ) + + val nonSmokingDataMen = nonSmokingDataWomen.copy( + age40to44 = listOf( + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "< 4", risk = 4), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "4 - 4.9", risk = 4), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "5 - 5.9", risk = 4), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = "6 - 6.9", risk = 5), + LabBasedRiskEntry(systolic = "140 - 159", cholesterol = ">= 7", risk = 6), + ) + ) + + val menGenderData = Men( + smoking = smokingDataMen, + nonSmoking = nonSmokingDataMen + ) + + return LabBasedCVDRiskCalculationSheet( + diabetes = LabBasedCVDRiskCalculationSheet.DiabetesRisk( + women = womenGenderData, + men = menGenderData + ), + noDiabetes = LabBasedCVDRiskCalculationSheet.DiabetesRisk( + women = womenGenderData, + men = menGenderData + ) + ) + } }