Verbrauch: Tankstand ab Fahrtbeginn statt davor (2026.9.1.24)
DER VERBRAUCH WAR SYSTEMATISCH ZU HOCH Der Startwert kam aus wert_bei(), also dem letzten Literstand VOR der Fahrt - und das ist im Stand der Wert vom Ende der VORIGEN Fahrt. An der Fahrt Eichstaett - Adelschlag nachgemessen: 36,4 l um 13:52 (Ende der vorigen Fahrt), 36,2 l um 16:20:49 (erster Datensatz der neuen). In der Standzeit dazwischen ist niemand gefahren; diese 0,2 l Setzung wurden der neuen Fahrt zugerechnet. alt: 36,4 - 35,6 = 0,8 l auf 6,896 km -> 11,6 l/100 km neu: 36,2 - 35,6 = 0,6 l auf 6,896 km -> 8,7 l/100 km Neu wert_ab() in verlauf.py: der erste Wert AB dem Zeitpunkt. Fuer einen ZAEHLER ist "zuletzt davor" richtig (der Kilometerstand aendert sich im Stand nicht), fuer einen gemessenen FUELLSTAND nicht - der driftet. Das Fahrtende bleibt bei wert_bei(). Livepfad und Rueckblick benutzen beide die neue Funktion. Bereits gerechnete Fahrten behalten ihren Wert: _verbrauch_screenen() fuellt nur fehlende. Die Neuberechnung kommt mit dem Korrekturwert aus den Tankvorgaengen, den der Eigentuemer vorgeschlagen hat. ANZEIGE Hoechstgeschwindigkeit ohne Nachkommastelle. Statuswort raus aus der Fahrtenliste - "vollstaendig" sagt dem Nutzer nichts, und "offen" verspricht Daten, die bei einer laengst abgeschlossenen Fahrt nie mehr kommen; fehlt ein Wert, steht dort ein Strich. Strecke und Verbrauch stehen jetzt in einer Spalte: die Wertspalte wuchs mit dem Inhalt, gemessen 86px gegen 37px, und die Zahlen standen versetzt. Feste Mindestbreite in beiden Oberflaechen, nachgemessen alle Zeilen 92px. Verifiziert: py_compile, Panel als Modul, tsc --noEmit sauber, 165/165 Tests, wert_ab() gegen vier Randfaelle, im Browser nachgesehen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -213,7 +213,7 @@ export function FahrtDetail({ id, geheZu }: { id: string | undefined; geheZu: (n
|
||||
<Wertzeile
|
||||
label="Höchstgeschwindigkeit"
|
||||
wert={
|
||||
fahrt.vmax_kmh != null ? `${de(fahrt.vmax_kmh, 1)} km/h` : "liegt nicht vor"
|
||||
fahrt.vmax_kmh != null ? `${de(fahrt.vmax_kmh)} km/h` : "liegt nicht vor"
|
||||
}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -112,13 +112,15 @@ export function Fahrten({ geheZu }: { geheZu: (name: SeitenName, id?: string) =>
|
||||
<Blattzeile
|
||||
label={strecke(fahrt)}
|
||||
labelZusatz={`${datum(fahrt.ts_start)} · ${artText(fahrt.art)}`}
|
||||
wert={
|
||||
streckeText(fahrt.distance_km, "offen")
|
||||
}
|
||||
wert={streckeText(fahrt.distance_km, "—")}
|
||||
wertZusatz={
|
||||
/* Kein Statuswort mehr: "vollstaendig" sagt dem Nutzer nichts,
|
||||
und "offen" verspricht Daten, die bei einer laengst
|
||||
abgeschlossenen Fahrt nie mehr kommen. Fehlt der Wert,
|
||||
steht dort ein Strich. */
|
||||
fahrt.verbrauch_l_100km != null
|
||||
? `${de(fahrt.verbrauch_l_100km, 1)} l/100 km`
|
||||
: fahrt.status
|
||||
: "—"
|
||||
}
|
||||
beiKlick={() => geheZu("trip", fahrt.trip_id)}
|
||||
letzte={i === monat.eintraege.length - 1}
|
||||
|
||||
@@ -1014,8 +1014,13 @@ button.dm-blatt:active {
|
||||
color: var(--fg);
|
||||
}
|
||||
|
||||
/* Feste Mindestbreite, damit Strecke und Verbrauch ueber alle Zeilen hinweg in
|
||||
einer Spalte stehen. Ohne sie waechst der Kasten mit dem Inhalt - im Panel
|
||||
gemessen 86px bei "11,4 l/100 km" gegen 37px bei einer Zeile ohne Werte, und
|
||||
die Zahlen standen entsprechend versetzt. */
|
||||
.dm-blatt__v {
|
||||
flex: 0 0 auto;
|
||||
min-width: 104px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":"2026.9.1.23","sha256":"c3e1376f4e314b2994bc6341c423b92d251142e0abd2abe4752e1f5f1a578d13","bytes":266223,"gebaut":"2026-09-01T18:35:21Z"}
|
||||
{"version":"2026.9.1.24","sha256":"1d08e5fe05d30095db34e6eaaf5f9765dad94c8e14fbc1a501cfe3e5daec572a","bytes":266230,"gebaut":"2026-09-01T19:12:38Z"}
|
||||
Binary file not shown.
@@ -1503,7 +1503,7 @@ function teaser() {
|
||||
return `<div class="tile teaser"><span class="label">Zuletzt</span>
|
||||
${t ? `<button class="leaf" style="padding-left:0" data-go="trip:${t.trip_id}">
|
||||
<span class="k">Letzte Fahrt<small>${esc(t.start_address || "")} → ${esc(t.end_address || "")}</small></span>
|
||||
<span class="v">${streckeText(t.distance_km, "offen")}<small>${t.status}</small></span>
|
||||
<span class="v">${streckeText(t.distance_km, "—")}<small>${fahrtVerbrauch(t) != null ? de(fahrtVerbrauch(t), 1) + " l/100 km" : "—"}</small></span>
|
||||
<svg class="chev" viewBox="0 0 6 10"><polyline points="1,1 5,5 1,9"/></svg></button>` : ""}
|
||||
${f ? `<button class="leaf" style="padding-left:0;border-bottom:0" data-go="fill:${f.tank_id}">
|
||||
<span class="k">Letzter Tankvorgang<small>${esc(f.station_name || "")}</small></span>
|
||||
@@ -3636,7 +3636,7 @@ function vTrips() {
|
||||
tm.forEach((t) => { h += swipeZeile(`trip:${t.trip_id}`, `<button class="leaf" data-go="trip:${t.trip_id}">
|
||||
<span class="k">${strecke(t)}
|
||||
<small>${dedat(new Date(t.ts_start))} · ${artText(t.art)}</small></span>
|
||||
<span class="v">${streckeText(t.distance_km, "offen")}<small>${fahrtVerbrauch(t) != null ? de(fahrtVerbrauch(t), 1) + " l/100 km" : t.status}</small></span>
|
||||
<span class="v">${streckeText(t.distance_km, "—")}<small>${fahrtVerbrauch(t) != null ? de(fahrtVerbrauch(t), 1) + " l/100 km" : "—"}</small></span>
|
||||
<svg class="chev" viewBox="0 0 6 10"><polyline points="1,1 5,5 1,9"/></svg></button>`); });
|
||||
h += `</div></div>`;
|
||||
});
|
||||
@@ -3675,7 +3675,7 @@ function vTrip(id) {
|
||||
<div class="row"><dt>Endkilometer</dt><dd>${t.odo_end != null ? de(t.odo_end) + " km" : "noch offen"}</dd></div>
|
||||
<div class="row"><dt>Dauer</dt><dd>${dauerText(t.duration_s)}</dd></div>
|
||||
<div class="row"><dt>Ø Geschwindigkeit</dt><dd>${t.avg_speed_kmh != null ? de(t.avg_speed_kmh, 1) + " km/h" : "liegt nicht vor"}</dd></div>
|
||||
<div class="row"><dt>Höchstgeschwindigkeit</dt><dd>${t.vmax_kmh != null ? de(t.vmax_kmh, 1) + " km/h" : "liegt nicht vor"}</dd></div>
|
||||
<div class="row"><dt>Höchstgeschwindigkeit</dt><dd>${t.vmax_kmh != null ? de(t.vmax_kmh) + " km/h" : "liegt nicht vor"}</dd></div>
|
||||
<div class="row"><dt>Verbrauch</dt><dd>${fahrtVerbrauch(t) != null ? de(fahrtVerbrauch(t), 1) + " l/100 km" : "liegt nicht vor"}</dd></div>
|
||||
</dl>
|
||||
<button class="aktion" data-fahrtbearbeiten>Werte bearbeiten</button>
|
||||
|
||||
@@ -461,7 +461,12 @@ button.sicherheitszeile:active { background: var(--tile-2); }
|
||||
}
|
||||
.leaf .k { font-size: 14px; color: var(--fg); display: flex; flex-direction: column; gap: 3px; line-height: 1.35; }
|
||||
.leaf .k small { font-size: 12.5px; color: var(--fg3); }
|
||||
.leaf .v { font-size: 13px; color: var(--fg2); text-align: right; display: flex; flex-direction: column; gap: 3px; flex: 0 0 auto; }
|
||||
/* Feste Mindestbreite, damit Strecke und Verbrauch ueber alle Zeilen hinweg
|
||||
in einer Spalte stehen. Ohne sie waechst der Kasten mit dem Inhalt: gemessen
|
||||
86px bei "11,4 l/100 km" gegen 37px bei einer Zeile ohne Werte, und die
|
||||
Zahlen standen entsprechend versetzt. 92px traegt die laengste Form
|
||||
("11,4 l/100 km") ohne Umbruch. */
|
||||
.leaf .v { font-size: 13px; color: var(--fg2); text-align: right; display: flex; flex-direction: column; gap: 3px; flex: 0 0 auto; min-width: 92px; }
|
||||
.leaf .v small { font-size: 12.5px; color: var(--fg3); }
|
||||
/* .teaser (die "Zuletzt"-Kachel auf der Übersicht, teaser()): genau zwei
|
||||
Zeilen mit sehr unterschiedlich breiten Werten ("offen" vs. "51,59 l") -
|
||||
|
||||
@@ -57,6 +57,7 @@ from .verlauf import (
|
||||
verbrauch_aus_literstaenden,
|
||||
verlauf_lesen,
|
||||
Verlaufspunkt,
|
||||
wert_ab,
|
||||
wert_bei,
|
||||
wert_in_naehe,
|
||||
zahl,
|
||||
@@ -256,7 +257,9 @@ async def _fahrten_importieren(k: Koordinator, verlaeufe: dict) -> dict:
|
||||
"end_lon": wert_bei(lon_verlauf, f_ende),
|
||||
"route": route_aus_verlauf(lat_verlauf, lon_verlauf, f_start, f_ende),
|
||||
"verbrauch_l_100km": verbrauch_aus_literstaenden(
|
||||
wert_bei(tank_liter_verlauf, f_start), wert_bei(tank_liter_verlauf, f_ende), distanz
|
||||
# Erster Stand AB Fahrtbeginn, siehe wert_ab() - beide Wege
|
||||
# muessen dieselbe Fahrt gleich bewerten.
|
||||
wert_ab(tank_liter_verlauf, f_start), wert_bei(tank_liter_verlauf, f_ende), distanz
|
||||
),
|
||||
"status": "vollständig" if distanz is not None else "offen",
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"domain": "audi_dashboard",
|
||||
"name": "Audi Dashboard",
|
||||
"version": "2026.9.1.23",
|
||||
"version": "2026.9.1.24",
|
||||
"documentation": "https://gitea.nothaft.cloud/paul/audi-app/src/branch/main/README.md",
|
||||
"issue_tracker": "https://gitea.nothaft.cloud/paul/audi-app/issues",
|
||||
"codeowners": ["@paul"],
|
||||
|
||||
@@ -41,6 +41,7 @@ from .verlauf import (
|
||||
route_aus_verlauf,
|
||||
verbrauch_aus_literstaenden,
|
||||
verlauf_lesen,
|
||||
wert_ab,
|
||||
wert_bei,
|
||||
)
|
||||
|
||||
@@ -338,13 +339,12 @@ async def _verbrauch_screenen(
|
||||
if not verlauf:
|
||||
return
|
||||
|
||||
# wert_bei() aus demselben Grund wie beim Kilometerstand (siehe Modulkopf):
|
||||
# der Tankstand zu Fahrtbeginn ist der zuletzt DAVOR gemeldete, nicht der
|
||||
# zeitlich nächstgelegene - der läge womöglich schon in der Fahrt und hätte
|
||||
# einen Teil des Verbrauchs vorweggenommen. historienimport.py liest ihn
|
||||
# seit jeher so.
|
||||
# Anders als beim Kilometerstand: fuer den Tankstand gilt der erste Wert AB
|
||||
# dem Fahrtbeginn, nicht der letzte davor. Ein Fuellstand ist keine
|
||||
# Zaehlung, er driftet im Stand - siehe wert_ab() in verlauf.py fuer die
|
||||
# Messung, die das gezeigt hat. Das Ende bleibt bei wert_bei().
|
||||
verbrauch = verbrauch_aus_literstaenden(
|
||||
wert_bei(verlauf, start), wert_bei(verlauf, ende), fahrt.get("distance_km")
|
||||
wert_ab(verlauf, start), wert_bei(verlauf, ende), fahrt.get("distance_km")
|
||||
)
|
||||
if verbrauch is not None:
|
||||
await k.ablage.fahrt_aktualisieren(fahrt["trip_id"], {"verbrauch_l_100km": verbrauch})
|
||||
|
||||
@@ -244,6 +244,37 @@ def wert_bei(
|
||||
return davor
|
||||
|
||||
|
||||
def wert_ab(
|
||||
verlauf: list[Verlaufspunkt], zeitpunkt: datetime.datetime
|
||||
) -> float | None:
|
||||
"""Der erste ab `zeitpunkt` gemeldete Zahlenwert, sonst der letzte davor.
|
||||
|
||||
Gegenstueck zu wert_bei(). Fuer einen ZAEHLER ist -zuletzt davor- richtig
|
||||
(der Kilometerstand aendert sich im Stand nicht), fuer einen gemessenen
|
||||
FUELLSTAND nicht: der driftet.
|
||||
|
||||
Am 01.09.2026 an der Fahrt Eichstaett - Adelschlag nachgemessen. Der
|
||||
Tankstand stand am Ende der vorigen Fahrt (13:52) auf 36,4 l, beim ersten
|
||||
Datensatz der neuen Fahrt (16:20:49) auf 36,2 l - in der Standzeit dazwischen
|
||||
ist niemand gefahren. Diese 0,2 l Setzung wurden der neuen Fahrt zugerechnet:
|
||||
0,8 l statt 0,6 l auf 6,9 km, also **11,4 statt 8,7 l/100 km**.
|
||||
|
||||
Das Fahrtende bleibt bei wert_bei(): dort ist die Fahrt vorbei, und der
|
||||
letzte waehrend der Fahrt gemeldete Stand ist der richtige - der naechste
|
||||
kaeme erst Stunden spaeter und traege dieselbe Setzung wieder herein."""
|
||||
danach = None
|
||||
for ts, wert in verlauf:
|
||||
gezahlt = zahl(wert)
|
||||
if gezahlt is None:
|
||||
continue
|
||||
if ts >= zeitpunkt:
|
||||
danach = gezahlt
|
||||
break
|
||||
if danach is not None:
|
||||
return danach
|
||||
return wert_bei(verlauf, zeitpunkt)
|
||||
|
||||
|
||||
def route_aus_verlauf(
|
||||
lat_verlauf: list[Verlaufspunkt],
|
||||
lon_verlauf: list[Verlaufspunkt],
|
||||
|
||||
Reference in New Issue
Block a user