mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-14 18:26:11 -04:00
fix(overview): Stop denying a charge the reading still allows
The visible count came from the pessimistic end of the interval alone, so an interval straddling a full charge said "Less than one more full charge" while the colour stayed neutral and TalkBack said "may not be enough". An uncertain interval now rounds to a single charge instead, and an open-ended spec that has not reached one charge names no number at all. Fixes review finding F2
This commit is contained in:
@@ -513,6 +513,7 @@ private fun CaseChargesLine(
|
||||
val text = when (charges.display) {
|
||||
CaseCharges.Display.EMPTY -> stringResource(R.string.battery_case_charges_empty)
|
||||
CaseCharges.Display.LESS_THAN_ONE -> stringResource(R.string.battery_case_charges_less_than_one)
|
||||
CaseCharges.Display.UNCERTAIN -> stringResource(R.string.battery_case_charges_uncertain)
|
||||
CaseCharges.Display.AT_LEAST -> pluralStringResource(
|
||||
R.plurals.battery_case_charges_at_least,
|
||||
charges.count,
|
||||
|
||||
@@ -14,6 +14,9 @@ data class CaseCharges(
|
||||
/** Nothing left to give — distinct from [LESS_THAN_ONE], which still implies some charge. */
|
||||
EMPTY,
|
||||
LESS_THAN_ONE,
|
||||
|
||||
/** No number at all: an open-ended interval that has not yet reached a full charge. */
|
||||
UNCERTAIN,
|
||||
AT_LEAST,
|
||||
APPROXIMATE,
|
||||
}
|
||||
@@ -32,6 +35,10 @@ data class CaseCharges(
|
||||
*
|
||||
* A spec that is itself a lower bound has no upper end, so it can never claim "not enough".
|
||||
*
|
||||
* The wording follows the whole interval, not its pessimistic end: an uncertain one rounds to a
|
||||
* single charge, or names no number at all ([CaseCharges.Display.UNCERTAIN]) when the spec is a
|
||||
* lower bound and there is no upper end to round from.
|
||||
*
|
||||
* Null when the model publishes no case figures or the reading is missing or nonsense — the caller
|
||||
* shows no line at all rather than a neutral one.
|
||||
*/
|
||||
@@ -50,13 +57,23 @@ fun caseCharges(spec: PodModel.CaseSpec?, reading: BatteryReading?): CaseCharges
|
||||
else -> CaseCharges.Adequacy.UNCERTAIN
|
||||
}
|
||||
|
||||
val count = floor(lowest).toInt()
|
||||
val floored = floor(lowest).toInt()
|
||||
|
||||
val display = when {
|
||||
reading.percent == 0f -> CaseCharges.Display.EMPTY
|
||||
count < 1 -> CaseCharges.Display.LESS_THAN_ONE
|
||||
adequacy == CaseCharges.Adequacy.NOT_ENOUGH -> CaseCharges.Display.LESS_THAN_ONE
|
||||
adequacy == CaseCharges.Adequacy.UNCERTAIN && spec.isLowerBound -> CaseCharges.Display.UNCERTAIN
|
||||
adequacy == CaseCharges.Adequacy.UNCERTAIN -> CaseCharges.Display.APPROXIMATE
|
||||
spec.isLowerBound -> CaseCharges.Display.AT_LEAST
|
||||
else -> CaseCharges.Display.APPROXIMATE
|
||||
}
|
||||
|
||||
val count = when {
|
||||
reading.percent == 0f -> 0
|
||||
adequacy == CaseCharges.Adequacy.NOT_ENOUGH -> 0
|
||||
adequacy == CaseCharges.Adequacy.UNCERTAIN && !spec.isLowerBound -> 1
|
||||
else -> floored
|
||||
}
|
||||
|
||||
return CaseCharges(count = count, display = display, adequacy = adequacy)
|
||||
}
|
||||
|
||||
@@ -287,6 +287,8 @@
|
||||
</plurals>
|
||||
<string name="battery_case_charges_less_than_one">Less than one more full charge for both earbuds</string>
|
||||
<string name="battery_case_charges_empty">Case is empty, no charges left for your earbuds</string>
|
||||
<!-- Shown when the case reading is too coarse to name any number of charges. Must not mention a count. -->
|
||||
<string name="battery_case_charges_uncertain">Not sure how many full charges are left for both earbuds</string>
|
||||
<string name="battery_case_charges_state_enough_cd">Enough for a full charge</string>
|
||||
<string name="battery_case_charges_state_not_enough_cd">Not enough for a full charge</string>
|
||||
<string name="battery_case_charges_state_uncertain_cd">May not be enough for a full charge</string>
|
||||
|
||||
@@ -92,11 +92,19 @@ class CaseChargesLineTest : BaseComposeRobolectricTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a reading astride a full charge claims nothing`() {
|
||||
fun `a reading astride a full charge rounds to one`() {
|
||||
setCard(device(case = 0.20f))
|
||||
|
||||
assertAdequacy(charges(1), R.string.battery_case_charges_state_uncertain_cd)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `an open ended spec below a full charge names no number`() {
|
||||
// AirPods (Gen 1) publish a lower bound, so 3.8 x 0.10 has no upper end to round to
|
||||
setCard(device(case = 0.10f, model = PodModel.AIRPODS_GEN1))
|
||||
|
||||
assertAdequacy(
|
||||
context.getString(R.string.battery_case_charges_less_than_one),
|
||||
context.getString(R.string.battery_case_charges_uncertain),
|
||||
R.string.battery_case_charges_state_uncertain_cd,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -107,10 +107,36 @@ class CaseChargesTest : BaseTest() {
|
||||
@Test
|
||||
fun `below a full charge renders as less than one`() {
|
||||
charges(exact, 0.20f, percent)!!.display shouldBe CaseCharges.Display.LESS_THAN_ONE
|
||||
charges(lowerBound, 0.20f, percent)!!.display shouldBe CaseCharges.Display.LESS_THAN_ONE
|
||||
charges(exact, 0.01f, percent)!!.display shouldBe CaseCharges.Display.LESS_THAN_ONE
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `an interval straddling one charge rounds to one instead of claiming less`() {
|
||||
// 4.0 x 0.20 = 0.8, 4.0 x 0.30 = 1.2 — the text must not deny what the interval allows
|
||||
val straddle = charges(exact, 0.20f, decile)!!
|
||||
straddle.display shouldBe CaseCharges.Display.APPROXIMATE
|
||||
straddle.count shouldBe 1
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `an uncertain lower bound spec names no number`() {
|
||||
// 3.8 x 0.10 = 0.38 with no upper end, so neither "less than one" nor "~1" is supportable
|
||||
val vague = charges(lowerBound, 0.10f, decile)!!
|
||||
vague.adequacy shouldBe CaseCharges.Adequacy.UNCERTAIN
|
||||
vague.display shouldBe CaseCharges.Display.UNCERTAIN
|
||||
|
||||
charges(lowerBound, 0.20f, percent)!!.display shouldBe CaseCharges.Display.UNCERTAIN
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a lower bound spec that reaches enough still counts`() {
|
||||
val enough = charges(lowerBound, 0.50f, decile)!!
|
||||
enough.adequacy shouldBe CaseCharges.Adequacy.ENOUGH
|
||||
enough.display shouldBe CaseCharges.Display.AT_LEAST
|
||||
// 3.8 x 0.50 = 1.9
|
||||
enough.count shouldBe 1
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `an empty case renders as empty`() {
|
||||
charges(exact, 0f, percent)!!.display shouldBe CaseCharges.Display.EMPTY
|
||||
|
||||
Reference in New Issue
Block a user