Doctor summary: one-page PDF via PdfDocument + FileProvider share
Milestone 7. Human-readable A4 summary (meds, schedule, supply days, rx expiry/reit, 30-day adherence, notes) — deliberately distinct from the machine-readable JSON backup, zero PDF dependencies. The Norwegian schedule phrasing (ScheduleText) and adherence math are pure and unit-tested; a wrong schedule line on a doctor's desk is a clinical communication error, so it gets engine-grade testing. FileProvider exposes only cacheDir/summaries. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
c66bee5cf0
commit
e9a6679242
6 changed files with 279 additions and 0 deletions
48
app/src/main/java/no/naiv/meddetsamme/domain/ScheduleText.kt
Normal file
48
app/src/main/java/no/naiv/meddetsamme/domain/ScheduleText.kt
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package no.naiv.meddetsamme.domain
|
||||
|
||||
import no.naiv.meddetsamme.data.DoseTime
|
||||
|
||||
/**
|
||||
* Human-readable schedule descriptions (Norwegian, 24h) for the doctor
|
||||
* summary and the UI. Pure — unit-tested like the engine, since a wrong
|
||||
* description on a doctor's desk is a clinical communication error.
|
||||
*/
|
||||
object ScheduleText {
|
||||
|
||||
/** Mask bit order matches ScheduleEngine: bit 0 = Sunday. */
|
||||
private val DAY_ABBREV = listOf("søn", "man", "tir", "ons", "tor", "fre", "lør")
|
||||
|
||||
fun describe(doseTime: DoseTime): String {
|
||||
val time = "%02d:%02d".format(doseTime.minuteOfDay / 60, doseTime.minuteOfDay % 60)
|
||||
return "$time ${daysText(doseTime)}"
|
||||
}
|
||||
|
||||
fun daysText(doseTime: DoseTime): String {
|
||||
if (doseTime.intervalDays > 1) {
|
||||
return "(hver ${doseTime.intervalDays}. dag)"
|
||||
}
|
||||
return when (val mask = doseTime.daysOfWeekMask and 0x7F) {
|
||||
0x7F -> "(daglig)"
|
||||
0x3E -> "(man–fre)"
|
||||
0x41 -> "(lør–søn)"
|
||||
0 -> "(aldri)"
|
||||
else -> {
|
||||
// Week listed Monday-first for humans, despite bit 0 = Sunday.
|
||||
val days = (1..7).map { it % 7 }
|
||||
.filter { mask and (1 shl it) != 0 }
|
||||
.map { DAY_ABBREV[it] }
|
||||
"(${days.joinToString(", ")})"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** "1 tablett", "2,5 ml" — norsk desimalkomma. */
|
||||
fun amountText(amount: Double, unit: String): String {
|
||||
val number = if (amount == amount.toLong().toDouble()) {
|
||||
amount.toLong().toString()
|
||||
} else {
|
||||
amount.toString().replace('.', ',')
|
||||
}
|
||||
return "$number $unit"
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue