From 70830cf2cabe148ceff87352a8b9600bb1247874 Mon Sep 17 00:00:00 2001 From: darken Date: Tue, 25 Aug 2026 20:59:47 +0200 Subject: [PATCH] fix(overview): Call a case exactly one charge short "not enough" The reading is an interval that excludes its upper end, so an upper end landing exactly on one full charge still leaves every reachable value below one. AirPods Gen 4 at 10% and Pro 3 at 40% read neutral instead of orange because of it. Fixes review finding F1 --- .../eu/darken/capod/monitor/core/battery/CaseCharges.kt | 4 +++- .../darken/capod/monitor/core/battery/CaseChargesTest.kt | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/eu/darken/capod/monitor/core/battery/CaseCharges.kt b/app/src/main/java/eu/darken/capod/monitor/core/battery/CaseCharges.kt index cbc8ece7..95f0822b 100644 --- a/app/src/main/java/eu/darken/capod/monitor/core/battery/CaseCharges.kt +++ b/app/src/main/java/eu/darken/capod/monitor/core/battery/CaseCharges.kt @@ -28,6 +28,8 @@ data class CaseCharges( * makes a claim; anything straddling it is [CaseCharges.Adequacy.UNCERTAIN]. That also absorbs the * bounce between adjacent readings, so no state has to be remembered between frames. * + * The interval excludes its upper end, so an upper end of exactly one charge is still short of one. + * * A spec that is itself a lower bound has no upper end, so it can never claim "not enough". * * Null when the model publishes no case figures or the reading is missing or nonsense — the caller @@ -44,7 +46,7 @@ fun caseCharges(spec: PodModel.CaseSpec?, reading: BatteryReading?): CaseCharges val adequacy = when { lowest >= 1f -> CaseCharges.Adequacy.ENOUGH spec.isLowerBound -> CaseCharges.Adequacy.UNCERTAIN - highest < 1f -> CaseCharges.Adequacy.NOT_ENOUGH + highest <= 1f -> CaseCharges.Adequacy.NOT_ENOUGH else -> CaseCharges.Adequacy.UNCERTAIN } diff --git a/app/src/test/java/eu/darken/capod/monitor/core/battery/CaseChargesTest.kt b/app/src/test/java/eu/darken/capod/monitor/core/battery/CaseChargesTest.kt index 4a2118e6..1a763afe 100644 --- a/app/src/test/java/eu/darken/capod/monitor/core/battery/CaseChargesTest.kt +++ b/app/src/test/java/eu/darken/capod/monitor/core/battery/CaseChargesTest.kt @@ -64,6 +64,15 @@ class CaseChargesTest : BaseTest() { charges(exact, 0.20f, percent)!!.adequacy shouldBe CaseCharges.Adequacy.NOT_ENOUGH } + @Test + fun `an interval ending exactly on one charge is not enough`() { + // the top of the interval is excluded, so 5.0 x (0.10 + 0.10) = 1.0 is still short + charges(PodModel.CaseSpec(fullPairRecharges = 5.0f), 0.10f, decile)!! + .adequacy shouldBe CaseCharges.Adequacy.NOT_ENOUGH + // 4.0 x (0.24 + 0.01) = 1.0 + charges(exact, 0.24f, percent)!!.adequacy shouldBe CaseCharges.Adequacy.NOT_ENOUGH + } + @Test fun `an interval straddling one charge claims nothing`() { // 4.0 x 0.20 = 0.8, 4.0 x 0.30 = 1.2