fix(manager): Batterie als neutralen Restregler behandeln
Tests / test (push) Successful in 51s

This commit is contained in:
dh
2026-09-29 14:38:14 +00:00
parent fdc2007bb1
commit 3aaa744a8a
2 changed files with 113 additions and 11 deletions
+74 -8
View File
@@ -155,22 +155,29 @@ final class ManagerRegler
$verteilbudget = (int) round($aktuelleLeistung + $zielnetzleistung - $netzleistung);
$sollwerte = [];
$minimumSumme = 0;
$ausgangssumme = 0;
foreach ($steuerbar as $eintrag) {
$minimum = self::kleinsterLeistungswert($eintrag['Leistungswerte_W']);
$sollwerte[$eintrag['InstanzID']] = $minimum;
$minimumSumme += $minimum;
$ausgangswert = self::neutralerLeistungswert($eintrag['Leistungswerte_W']);
$sollwerte[$eintrag['InstanzID']] = $ausgangswert;
$ausgangssumme += $ausgangswert;
}
$verfuegbar = max(0, $verteilbudget - $nichtSteuerbar - $minimumSumme);
$rest = $verteilbudget - $nichtSteuerbar - $ausgangssumme;
foreach ($steuerbar as $eintrag) {
$instanzID = $eintrag['InstanzID'];
$minimum = $sollwerte[$instanzID];
$ausgangswert = $sollwerte[$instanzID];
if ($rest >= 0) {
$neuerSollwert = self::groessterLeistungswertBis(
$eintrag['Leistungswerte_W'],
$minimum + $verfuegbar
$ausgangswert + $rest
);
$verfuegbar -= $neuerSollwert - $minimum;
} else {
$neuerSollwert = self::kleinsterLeistungswertAb(
$eintrag['Leistungswerte_W'],
$ausgangswert + $rest
);
}
$rest -= $neuerSollwert - $ausgangswert;
$sollwerte[$instanzID] = $neuerSollwert;
}
@@ -231,6 +238,43 @@ final class ManagerRegler
}
}
/**
* @param list<int|array{Von_W: int, Bis_W: int}> $leistungswerte
*/
private static function neutralerLeistungswert(array $leistungswerte): int
{
$negativ = null;
$positiv = null;
foreach ($leistungswerte as $eintrag) {
if (is_int($eintrag)) {
if ($eintrag === 0) {
return 0;
}
$negativ = $eintrag < 0 ? max($negativ ?? $eintrag, $eintrag) : $negativ;
$positiv = $eintrag > 0 ? min($positiv ?? $eintrag, $eintrag) : $positiv;
continue;
}
if ($eintrag['Von_W'] <= 0 && $eintrag['Bis_W'] >= 0) {
return 0;
}
$negativ = $eintrag['Bis_W'] < 0
? max($negativ ?? $eintrag['Bis_W'], $eintrag['Bis_W'])
: $negativ;
$positiv = $eintrag['Von_W'] > 0
? min($positiv ?? $eintrag['Von_W'], $eintrag['Von_W'])
: $positiv;
}
if ($negativ === null) {
return $positiv;
}
if ($positiv === null) {
return $negativ;
}
return abs($negativ) <= abs($positiv) ? $negativ : $positiv;
}
/**
* @param list<int|array{Von_W: int, Bis_W: int}> $leistungswerte
*/
@@ -264,4 +308,26 @@ final class ManagerRegler
return $gewaehlt;
}
/**
* @param list<int|array{Von_W: int, Bis_W: int}> $leistungswerte
*/
private static function kleinsterLeistungswertAb(array $leistungswerte, int $untergrenze): int
{
foreach ($leistungswerte as $eintrag) {
if (is_int($eintrag)) {
if ($eintrag >= $untergrenze) {
return $eintrag;
}
continue;
}
if ($eintrag['Bis_W'] < $untergrenze) {
continue;
}
return max($eintrag['Von_W'], $untergrenze);
}
return self::neutralerLeistungswert($leistungswerte);
}
}
+36
View File
@@ -192,6 +192,42 @@ final class ManagerReglerTest extends TestCase
self::assertSame(0, $ergebnis['Restabweichung_W']);
}
public function testBatterieGleichtFesteLastenAusOhneSolarladungZuSpeisen(): void
{
$ergebnis = ManagerRegler::verteile(
-4526.0,
-50.0,
[
$this->verbraucher(29743, 1, [0, 6500], 6500),
$this->verbraucher(38676, 1, [0, 4600], 4600),
$this->verbraucher(22078, 2, [7690], 0, false),
$this->verbraucher(31986, 2, [11000], 10942, false),
$this->verbraucher(43878, 2, [0, 4150, 10300], 9908),
$this->verbraucher(
44234,
6,
[['Von_W' => -39000, 'Bis_W' => 39000]],
-22769
),
],
'PrioritaetPV'
);
self::assertSame(13657, $ergebnis['Verteilbudget_W']);
self::assertSame(
[
29743 => 0,
38676 => 0,
22078 => 7690,
31986 => 11000,
43878 => 0,
44234 => -5033,
],
$ergebnis['Sollwerte']
);
self::assertSame(0, $ergebnis['Restabweichung_W']);
}
public function testBegrenztesFahrzeugLaedtVorBatterieOhneBatterieentladung(): void
{
$ergebnis = ManagerRegler::verteile(