fix(manager): Fahrplanvorgabe linear interpolieren
This commit is contained in:
@@ -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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user