App 2.10.0: range since start, usage in its own cards
"Range since start" replaces the range at current power: remaining energy over the consumption since the car was switched on, standing with the climate on included. A trip starts again after 10 minutes without samples (the car was off) or when charging. The kWh/100 km for both estimates moved out of the range tiles into two cards of their own, directly below them; the overview still fits the full-screen 1920x720 display without scrolling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
This commit is contained in:
@@ -3,6 +3,7 @@ package com.evsuite.abrp;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -19,20 +20,49 @@ public class RangeEstimatorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void instantRangeFromPowerAndSpeed() {
|
||||
// 15 kW at 100 km/h = 15 kWh/100 km; 25.4 kWh left = 169.3 km.
|
||||
RangeEstimator.Estimate e = RangeEstimator.instant(25.4, 15f, 100f);
|
||||
assertNotNull(e);
|
||||
assertEquals(15.0, e.kwhPer100Km, 1e-9);
|
||||
assertEquals(169.333, e.rangeKm, 0.001);
|
||||
public void sinceStartCoversTheWholeTripNotJustFiveMinutes() {
|
||||
RangeEstimator r = new RangeEstimator();
|
||||
// 10 minutes at 30 kW then 10 minutes at 10 kW, both at 100 km/h: 20 kWh/100 km overall.
|
||||
for (long t = 0; t <= 600_000; t += 15_000) r.add(t, 30f, 100f);
|
||||
for (long t = 615_000; t <= 1_200_000; t += 15_000) r.add(t, 10f, 100f);
|
||||
RangeEstimator.Estimate trip = r.sinceStart(25.4);
|
||||
assertNotNull(trip);
|
||||
assertEquals(20.0, trip.kwhPer100Km, 0.2); // plus the 15 s step between the two
|
||||
assertEquals(127.0, trip.rangeKm, 1.0);
|
||||
assertEquals(33.3, trip.distanceKm, 0.1);
|
||||
// The 5-minute average only sees the economical end.
|
||||
assertEquals(10.0, r.average(25.4, 1_200_000).kwhPer100Km, 0.1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noInstantEstimateWhenStandingRegeneratingOrUnread() {
|
||||
assertNull(RangeEstimator.instant(25.4, 2f, 3f)); // not really moving
|
||||
assertNull(RangeEstimator.instant(25.4, -10f, 60f)); // regenerating
|
||||
assertNull(RangeEstimator.instant(25.4, null, 60f)); // power unread
|
||||
assertNull(RangeEstimator.instant(null, 15f, 60f)); // SOC unread
|
||||
public void standingWithTheClimateOnCountsTowardsTheTrip() {
|
||||
RangeEstimator r = new RangeEstimator();
|
||||
for (long t = 0; t <= 120_000; t += 15_000) r.add(t, 3f, 0f); // warming up
|
||||
for (long t = 135_000; t <= 735_000; t += 15_000) r.add(t, 15f, 60f);
|
||||
assertTrue(r.sinceStart(25.4).kwhPer100Km > 15.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aLongGapOrChargingStartsANewTrip() {
|
||||
RangeEstimator r = new RangeEstimator();
|
||||
for (long t = 0; t <= 600_000; t += 15_000) r.add(t, 30f, 100f);
|
||||
long later = 600_000 + RangeEstimator.TRIP_RESET_GAP_MS + 1; // the car was off
|
||||
for (long t = later; t <= later + 600_000; t += 15_000) r.add(t, 10f, 100f);
|
||||
assertEquals(10.0, r.sinceStart(25.4).kwhPer100Km, 0.1);
|
||||
|
||||
long charge = later + 615_000;
|
||||
r.add(charge, -7f, 0f); // plugged in
|
||||
assertNull(r.sinceStart(25.4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noSinceStartBeforeAnyDistanceOrWithoutSoc() {
|
||||
RangeEstimator r = new RangeEstimator();
|
||||
assertNull(r.sinceStart(25.4));
|
||||
for (long t = 0; t <= 60_000; t += 15_000) r.add(t, 2f, 0f);
|
||||
assertNull(r.sinceStart(25.4)); // not moved yet
|
||||
for (long t = 75_000; t <= 300_000; t += 15_000) r.add(t, 15f, 60f);
|
||||
assertNull(r.sinceStart(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user