mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-15 10:46:12 -04:00
fix(battery): Seed charge ETA from quick-charge specs, hide projection while charging
- While charging, the gauge showed the bare runtime projection when no charge
rate existed yet — "1% · 4m" next to a charging chip reads as a four-minute
charge. The line now shows the "until charged" ETA or nothing
- Seed the charge rate from Apple's published quick-charge claims ("5 minutes
in the case provides around 1 hour of listening"), normalized against the
rated listening hours, so the ETA is present from the very first charge; a
live fit still takes over within minutes
This commit is contained in:
@@ -267,6 +267,16 @@ class BatteryEstimatorTest : BaseTest() {
|
||||
left.minutesUntilCharged shouldBe 28
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `the quick-charge rating seeds an ETA on the very first charge`() = runTest(UnconfinedTestDispatcher()) {
|
||||
// Nothing measured, nothing stored — Apple's "5 minutes = ~1 hour of listening" claim
|
||||
// (2.0/hr for a Pro 2) answers at once: 50% missing at 2.0/hr == 15 min.
|
||||
val result = collectEstimate(
|
||||
estimator(listOf(listOf(device("p1", left = 0.50f, right = 0.50f, charging = true, model = PodModel.AIRPODS_PRO2))))
|
||||
)
|
||||
result["p1"].shouldNotBeNull().left.shouldNotBeNull().minutesUntilCharged shouldBe 15
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a stored charge rate seeds time-until-charged immediately`() = runTest(UnconfinedTestDispatcher()) {
|
||||
// First charging emission, no live fit possible yet -> the persisted rate answers at once.
|
||||
|
||||
@@ -155,6 +155,19 @@ class ModelFeaturesTest : BaseTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `every battery spec carries a plausible quick-charge rate`() {
|
||||
// Derived from Apple's published quick-charge claims; must sit inside the band the live
|
||||
// fit is validated against, or the seed could never be corrected by a measurement.
|
||||
PodModel.entries.forEach { model ->
|
||||
val spec = model.batterySpec ?: return@forEach
|
||||
withClue(model.name) {
|
||||
val rate = spec.chargeFractionPerHour
|
||||
(rate != null && rate in 0.25f..4.0f) shouldBe true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun modelsWith(predicate: (PodModel.Features) -> Boolean): Set<PodModel> = PodModel.entries
|
||||
.filter { predicate(it.features) }
|
||||
.toSet()
|
||||
|
||||
Reference in New Issue
Block a user