feat(manager): Fahrplanvorgabe linear interpolieren
Tests / test (push) Successful in 54s

This commit is contained in:
dh
2026-10-01 12:16:10 +00:00
parent add1077674
commit 38353aed93
3 changed files with 122 additions and 23 deletions
+65
View File
@@ -19,6 +19,71 @@ final class ManagerRegler
public const BETRIEBSART_PV = Nachrichtenvertrag::BETRIEBSART_PV;
public const BETRIEBSART_PEAK = Nachrichtenvertrag::BETRIEBSART_PEAK;
/**
* @param list<array<string, mixed>> $punkte
*/
public static function interpolierteFahrplanVorgabe(
array $punkte,
int $jetzt,
int $maximalerPunktabstandSekunden = 1800
): ?float {
if ($maximalerPunktabstandSekunden < 0) {
throw new InvalidArgumentException('Maximaler Fahrplanpunktabstand darf nicht negativ sein.');
}
$gueltigePunkte = [];
foreach ($punkte as $punkt) {
if (!is_array($punkt)
|| !is_string($punkt['time'] ?? null)
|| (!is_int($punkt['gridTargetW'] ?? null)
&& !is_float($punkt['gridTargetW'] ?? null))
) {
continue;
}
$zeitpunkt = strtotime($punkt['time']);
$vorgabe = (float) $punkt['gridTargetW'];
if ($zeitpunkt === false || !is_finite($vorgabe)) {
continue;
}
$gueltigePunkte[$zeitpunkt] = $vorgabe;
}
if ($gueltigePunkte === []) {
return null;
}
ksort($gueltigePunkte, SORT_NUMERIC);
$vorherigerZeitpunkt = null;
$vorherigeVorgabe = null;
foreach ($gueltigePunkte as $zeitpunkt => $vorgabe) {
if ($zeitpunkt === $jetzt) {
return $vorgabe;
}
if ($zeitpunkt > $jetzt) {
if ($vorherigerZeitpunkt === null) {
return $zeitpunkt - $jetzt <= $maximalerPunktabstandSekunden
? $vorgabe
: null;
}
if ($jetzt - $vorherigerZeitpunkt > $maximalerPunktabstandSekunden
|| $zeitpunkt - $jetzt > $maximalerPunktabstandSekunden
) {
return null;
}
$anteil = ($jetzt - $vorherigerZeitpunkt) / ($zeitpunkt - $vorherigerZeitpunkt);
return $vorherigeVorgabe + (($vorgabe - $vorherigeVorgabe) * $anteil);
}
$vorherigerZeitpunkt = $zeitpunkt;
$vorherigeVorgabe = $vorgabe;
}
return $vorherigerZeitpunkt !== null
&& $jetzt - $vorherigerZeitpunkt <= $maximalerPunktabstandSekunden
? $vorherigeVorgabe
: null;
}
/**
* @param array<int, float|int> $monatsgrenzen Monatsnummer 1 bis 12 als Schluessel
*/