Reisen: Wohnort und nachvollziehbare Kilometer-Rechnung

- Wohnort pro Konto (Tabelle travel_home), im Tab "Statistik" über die
  Städtesuche festlegen, auf der Karte als ⌂
- Kilometer (route.js): jede Reise mit Hin- und Heimweg ab Wohnort;
  Reisen mit höchstens einem Tag Abstand als Rundreise; Besuche während
  eines längeren Aufenthalts als Ausflug hin und zurück; ohne Wohnort
  werden Reisen direkt verbunden
- "Wie gerechnet?" listet alle Teilstrecken; Reisetage zählen jeden Tag
  nur einmal (Ausflüge im Aufenthalt nicht doppelt)
- Wohnort-Suche mit eigenen IDs (zwei Suchfelder auf der Seite)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
guyg1474andClaude Opus 5.5 committed 2026-10-15 20:31:52 +02:00
1 parent fdbb31065f
commit 56c4f38ef0
10 files changed
+210 -22

No files matched your search

+63
View File
@@ -0,0 +1,63 @@
// Reiseroute für die Kilometer-Statistik, aus den eingetragenen Besuchen (Luftlinie):
// - Reise: Wohnort → Ziel → Wohnort. Beginnt die nächste Reise höchstens einen Tag nach dem Ende der vorigen,
// ist es eine Rundreise (Wohnort → A → B → Wohnort).
// - Ausflug: Besuch, der während eines längeren Aufenthalts beginnt (z. B. David während San José) –
// zählt als Hin- und Rückweg zum Aufenthaltsort.
// Ohne Wohnort fehlen Hin- und Heimwege; die Reisen werden dann direkt nacheinander verbunden.
import { distanceKm } from './laender.js';
const day = (d) => Math.round(Date.parse(`${d}T12:00:00Z`) / 864e5);
export function travelRoute(visits, cities, home) {
const byId = new Map(cities.map((c) => [c.id, c]));
const items = visits
.map((v) => ({ ...v, city: byId.get(v.cityId), to: v.dateTo || v.dateFrom }))
.filter((v) => v.city)
.sort((a, b) => a.dateFrom.localeCompare(b.dateFrom) || b.to.localeCompare(a.to));
// Ausflüge ihrem Aufenthalt zuordnen
const trips = [];
for (const v of items) {
const base = trips.at(-1)?.visit;
if (base && v.dateFrom >= base.dateFrom && v.dateFrom <= base.to) trips.at(-1).excursions.push(v);
else trips.push({ visit: v, excursions: [] });
}
const legs = [];
const leg = (from, to, kind) => {
if (!from || !to || (from.lat === to.lat && from.lon === to.lon)) return;
legs.push({ from: from.name, to: to.name, km: distanceKm(from, to), kind });
};
let pos = null;
trips.forEach((t, i) => {
const chained = i > 0 && day(t.visit.dateFrom) - day(trips[i - 1].visit.to) <= 1;
if (home && !chained) {
leg(pos, home, 'Heimweg');
pos = home;
}
// Ohne Wohnort werden getrennte Reisen direkt verbunden – das ist dann eine Weiterreise, kein Hinweg
leg(pos, t.visit.city, chained || !home ? 'Weiterreise' : 'Hinweg');
pos = t.visit.city;
for (const ex of t.excursions) {
leg(pos, ex.city, 'Ausflug');
leg(ex.city, pos, 'Ausflug zurück');
}
});
if (home && trips.length) leg(pos, home, 'Heimweg');
return {
legs,
km: legs.reduce((s, l) => s + l.km, 0),
trips: trips.length,
excursions: trips.reduce((s, t) => s + t.excursions.length, 0),
};
}
// Reisetage: jeder Kalendertag nur einmal (Ausflüge während eines Aufenthalts zählen nicht doppelt)
export function travelDays(visits) {
const days = new Set();
for (const v of visits) {
for (let d = day(v.dateFrom); d <= day(v.dateTo || v.dateFrom); d += 1) days.add(d);
}
return days.size;
}