Skip to content

Commit 4253930

Browse files
committed
add screen and capture for statistics
1 parent 910a74c commit 4253930

9 files changed

Lines changed: 67 additions & 10 deletions

File tree

‎app/src/main/java/com/mg4/control/model/StatsPending.kt‎

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ data class PendingTrip(
1414
val odometerStart: Int?,
1515
val energyStart: Float?,
1616
val socStart: Float?,
17+
/** Première température relevée. Ne sert plus qu'à reprendre un état de l'ancien format. */
1718
val tempC: Float?,
1819
/** Dernier relevé observé pendant le trajet — celui qui servira de fin en cas de coupure. */
1920
val lastMs: Long,
@@ -23,6 +24,9 @@ data class PendingTrip(
2324
val climateLast: Float?,
2425
val accessoriesLast: Float?,
2526
val regenLast: Float?,
27+
/** Somme et nombre des températures relevées, pour en faire une moyenne. */
28+
val tempSum: Float = 0f,
29+
val tempCount: Int = 0,
2630
/** Distance accumulée en intégrant la vitesse, en km. Voir [Trip.integratedKm]. */
2731
val integratedKm: Float = 0f,
2832
/** Vitesse du relevé précédent, l'autre côté du trapèze. */
@@ -32,18 +36,37 @@ data class PendingTrip(
3236
* distinguerait pas d'une distance jamais mesurée — et l'écran annoncerait un trajet immobile.
3337
*/
3438
val integrated: Boolean = false,
35-
)
39+
) {
40+
val averageTempC: Float? get() = moyenne(tempSum, tempCount, tempC)
41+
}
3642

3743
data class PendingCharge(
3844
val startMs: Long,
3945
val socStart: Float?,
4046
val type: ChargeType?,
47+
/** Première température relevée. Ne sert plus qu'à reprendre un état de l'ancien format. */
4148
val tempC: Float?,
4249
val powerSum: Float,
4350
val powerCount: Int,
4451
val lastMs: Long,
4552
val socLast: Float?,
46-
)
53+
val tempSum: Float = 0f,
54+
val tempCount: Int = 0,
55+
) {
56+
val averageTempC: Float? get() = moyenne(tempSum, tempCount, tempC)
57+
}
58+
59+
/**
60+
* Moyenne des températures relevées pendant un trajet ou une charge, **et non celle du départ**.
61+
*
62+
* Le capteur extérieur de la MG4 est lent et mal placé : une voiture qui sort d'un garage annonce
63+
* la température du garage pendant plusieurs minutes. Sous contact, le collecteur relève à cadence
64+
* fixe, la moyenne des échantillons vaut donc une moyenne dans le temps.
65+
*
66+
* [repli] couvre un état enregistré avant cette mesure, qui ne portait que la première valeur.
67+
*/
68+
private fun moyenne(sum: Float, count: Int, repli: Float?): Float? =
69+
if (count > 0) (sum / count).roundTenth() else repli
4770

4871
/** Les deux ensemble, tels qu'ils sont enregistrés. */
4972
data class PendingState(

‎app/src/main/java/com/mg4/control/model/StatsTracker.kt‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ class StatsTracker(private val capacityKwh: Float = StatsSettings.DEFAULT_CAPACI
8585
energyStart = snapshot.energySinceStartKwh,
8686
socStart = snapshot.socPercent,
8787
tempC = snapshot.outsideTempC,
88+
tempSum = snapshot.outsideTempC ?: 0f,
89+
tempCount = if (snapshot.outsideTempC != null) 1 else 0,
8890
lastMs = snapshot.timestampMs,
8991
odometerLast = snapshot.odometerKm,
9092
energyLast = snapshot.energySinceStartKwh,
@@ -101,6 +103,9 @@ class StatsTracker(private val capacityKwh: Float = StatsSettings.DEFAULT_CAPACI
101103
climateLast = snapshot.climateSinceStartKwh ?: enCours.climateLast,
102104
accessoriesLast = snapshot.accessoriesSinceStartKwh ?: enCours.accessoriesLast,
103105
regenLast = snapshot.regenSinceStartKwh ?: enCours.regenLast,
106+
// Moyenne et non valeur de départ : voir [moyenne].
107+
tempSum = enCours.tempSum + (snapshot.outsideTempC ?: 0f),
108+
tempCount = enCours.tempCount + if (snapshot.outsideTempC != null) 1 else 0,
104109
integratedKm = enCours.integratedKm + (pas ?: 0f),
105110
integrated = enCours.integrated || pas != null,
106111
// Une vitesse manquée ne réinitialise pas le trapèze : le prochain intervalle
@@ -129,6 +134,8 @@ class StatsTracker(private val capacityKwh: Float = StatsSettings.DEFAULT_CAPACI
129134
socStart = snapshot.socPercent,
130135
type = snapshot.chargeType,
131136
tempC = snapshot.outsideTempC,
137+
tempSum = snapshot.outsideTempC ?: 0f,
138+
tempCount = if (snapshot.outsideTempC != null) 1 else 0,
132139
powerSum = 0f,
133140
powerCount = 0,
134141
lastMs = snapshot.timestampMs,
@@ -140,6 +147,10 @@ class StatsTracker(private val capacityKwh: Float = StatsSettings.DEFAULT_CAPACI
140147
lastMs = snapshot.timestampMs,
141148
socLast = snapshot.socPercent ?: chargeEnCours.socLast,
142149
type = chargeEnCours.type ?: snapshot.chargeType,
150+
// Une charge de nuit traverse plusieurs degrés : la moyenne dit quelque chose,
151+
// la température du branchement ne dit rien.
152+
tempSum = chargeEnCours.tempSum + (snapshot.outsideTempC ?: 0f),
153+
tempCount = chargeEnCours.tempCount + if (snapshot.outsideTempC != null) 1 else 0,
143154
)
144155
} else if (snapshot.charging == false && chargeEnCours != null) {
145156
events += Event.ChargeEnded(
@@ -191,7 +202,7 @@ class StatsTracker(private val capacityKwh: Float = StatsSettings.DEFAULT_CAPACI
191202
regenKwh = p.regenLast,
192203
socStart = p.socStart,
193204
socEnd = p.socLast,
194-
outsideTempC = p.tempC,
205+
outsideTempC = p.averageTempC,
195206
integratedKm = integre,
196207
)
197208
}
@@ -206,7 +217,7 @@ class StatsTracker(private val capacityKwh: Float = StatsSettings.DEFAULT_CAPACI
206217
socEnd = socEnd,
207218
energyKwh = delta?.takeIf { it > 0f }?.let { (it / 100f * capacityKwh).roundTenth() },
208219
measuredPowerKw = if (p.powerCount > 0) (p.powerSum / p.powerCount).roundTenth() else null,
209-
outsideTempC = p.tempC,
220+
outsideTempC = p.averageTempC,
210221
)
211222
}
212223

‎app/src/main/res/values-de/strings.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@
610610
<string name="stats_detail_accessories">Nebenverbraucher</string>
611611
<string name="stats_detail_regen">Rekuperation</string>
612612
<string name="stats_detail_battery">Batterie</string>
613-
<string name="stats_detail_temp">Außentemperatur</string>
613+
<string name="stats_detail_temp">Durchschnittstemperatur</string>
614614
<string name="stats_detail_power_measured">Mittlere Leistung, gemessen</string>
615615
<string name="stats_detail_power_computed">Mittlere Leistung, abgeleitet (Energie ÷ Dauer)</string>
616616
<string name="stats_detail_tariff">Angewandter Tarif</string>

‎app/src/main/res/values-en/strings.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@
610610
<string name="stats_detail_accessories">Accessories</string>
611611
<string name="stats_detail_regen">Regenerative braking</string>
612612
<string name="stats_detail_battery">Battery</string>
613-
<string name="stats_detail_temp">Outside temperature</string>
613+
<string name="stats_detail_temp">Average temperature</string>
614614
<string name="stats_detail_power_measured">Average power, measured</string>
615615
<string name="stats_detail_power_computed">Average power, derived (energy ÷ duration)</string>
616616
<string name="stats_detail_tariff">Rate applied</string>

‎app/src/main/res/values-es/strings.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@
610610
<string name="stats_detail_accessories">Accesorios</string>
611611
<string name="stats_detail_regen">Frenada regenerativa</string>
612612
<string name="stats_detail_battery">Batería</string>
613-
<string name="stats_detail_temp">Temperatura exterior</string>
613+
<string name="stats_detail_temp">Temperatura media</string>
614614
<string name="stats_detail_power_measured">Potencia media, medida</string>
615615
<string name="stats_detail_power_computed">Potencia media, deducida (energía ÷ duración)</string>
616616
<string name="stats_detail_tariff">Tarifa aplicada</string>

‎app/src/main/res/values-it/strings.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@
610610
<string name="stats_detail_accessories">Accessori</string>
611611
<string name="stats_detail_regen">Frenata rigenerativa</string>
612612
<string name="stats_detail_battery">Batteria</string>
613-
<string name="stats_detail_temp">Temperatura esterna</string>
613+
<string name="stats_detail_temp">Temperatura media</string>
614614
<string name="stats_detail_power_measured">Potenza media, misurata</string>
615615
<string name="stats_detail_power_computed">Potenza media, dedotta (energia ÷ durata)</string>
616616
<string name="stats_detail_tariff">Tariffa applicata</string>

‎app/src/main/res/values-pt/strings.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@
610610
<string name="stats_detail_accessories">Acessórios</string>
611611
<string name="stats_detail_regen">Travagem regenerativa</string>
612612
<string name="stats_detail_battery">Bateria</string>
613-
<string name="stats_detail_temp">Temperatura exterior</string>
613+
<string name="stats_detail_temp">Temperatura média</string>
614614
<string name="stats_detail_power_measured">Potência média, medida</string>
615615
<string name="stats_detail_power_computed">Potência média, deduzida (energia ÷ duração)</string>
616616
<string name="stats_detail_tariff">Tarifa aplicada</string>

‎app/src/main/res/values/strings.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@
623623
<string name="stats_detail_accessories">Accessoires</string>
624624
<string name="stats_detail_regen">Récupération au freinage</string>
625625
<string name="stats_detail_battery">Batterie</string>
626-
<string name="stats_detail_temp">Température extérieure</string>
626+
<string name="stats_detail_temp">Température moyenne</string>
627627
<string name="stats_detail_power_measured">Puissance moyenne mesurée</string>
628628
<string name="stats_detail_power_computed">Puissance moyenne déduite (énergie ÷ durée)</string>
629629
<string name="stats_detail_tariff">Tarif appliqué</string>

‎app/src/test/java/com/mg4/control/model/StatsTrackerTest.kt‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class StatsTrackerTest {
2727
regen: Float? = null,
2828
vitesse: Float? = null,
2929
pasMs: Long = 30_000L,
30+
temp: Float? = null,
3031
): EnergySnapshot {
3132
horloge += pasMs
3233
return EnergySnapshot(
@@ -39,6 +40,7 @@ class StatsTrackerTest {
3940
powerKw = puissance,
4041
regenSinceStartKwh = regen,
4142
speedKmh = vitesse,
43+
outsideTempC = temp,
4244
)
4345
}
4446

@@ -99,6 +101,27 @@ class StatsTrackerTest {
99101
assertEquals(20f, trip.distance, 0.01f)
100102
}
101103

104+
@Test
105+
fun `la temperature retenue est la moyenne du trajet, pas celle du depart`() {
106+
val t = StatsTracker()
107+
// Départ dans un garage à 18°, puis la vraie température dehors.
108+
t.onSnapshot(snap(odo = 10_000, temp = 18f), ready = true)
109+
t.onSnapshot(snap(odo = 10_010, temp = 6f), ready = true)
110+
t.onSnapshot(snap(odo = 10_020, temp = 4f), ready = true)
111+
val trip = finDe(t.onSnapshot(snap(odo = 10_020, temp = 4f), ready = false))!!
112+
assertEquals("(18 + 6 + 4) / 3", 9.3f, trip.outsideTempC!!, 0.05f)
113+
}
114+
115+
@Test
116+
fun `une charge de nuit retient la temperature moyenne`() {
117+
val t = StatsTracker()
118+
t.onSnapshot(snap(charge = true, soc = 20f, temp = 12f, type = ChargeType.AC), ready = false)
119+
t.onSnapshot(snap(charge = true, soc = 50f, temp = 6f, pasMs = 3_600_000L), ready = false)
120+
val session = (t.onSnapshot(snap(charge = false, soc = 80f, temp = 3f, pasMs = 3_600_000L), ready = false)
121+
.single() as StatsTracker.Event.ChargeEnded).session
122+
assertEquals("(12 + 6) / 2 — le relevé de fin clôt la session", 9f, session.outsideTempC!!, 0.05f)
123+
}
124+
102125
@Test
103126
fun `mettre le contact sans rouler ne cree pas de trajet`() {
104127
val t = StatsTracker()

0 commit comments

Comments
 (0)