This commit is contained in:
+96
-7
@@ -208,6 +208,7 @@ final class ManagerRegler
|
||||
'InstanzID' => $eintrag['InstanzID'],
|
||||
'Prioritaet' => $daten[$prioritaetsfeld],
|
||||
'Energiegruppe' => (int) round((float) $energie / 2000.0),
|
||||
'Energie_Wh' => (float) $energie,
|
||||
'Leistungswerte_W' => $daten['Leistungswerte_W'],
|
||||
'Festwert' => $festwert,
|
||||
'Festgehalten' => $festgehalten,
|
||||
@@ -254,6 +255,7 @@ final class ManagerRegler
|
||||
}
|
||||
|
||||
$rest = $verteilbudget - $nichtSteuerbar - $ausgangssumme;
|
||||
$gruppen = [];
|
||||
foreach ($steuerbar as $eintrag) {
|
||||
if ($eintrag['Festwert'] || $eintrag['Festgehalten']) {
|
||||
continue;
|
||||
@@ -262,13 +264,8 @@ final class ManagerRegler
|
||||
$instanzID = $eintrag['InstanzID'];
|
||||
$ausgangswert = $sollwerte[$instanzID];
|
||||
if ($positiveRichtung) {
|
||||
if ($rest <= 0) {
|
||||
continue;
|
||||
}
|
||||
$neuerSollwert = self::groessterLeistungswertBis(
|
||||
$eintrag['Leistungswerte_W'],
|
||||
$ausgangswert + $rest
|
||||
);
|
||||
$gruppen[$eintrag['Prioritaet']][] = $eintrag;
|
||||
continue;
|
||||
} else {
|
||||
if ($rest >= 0) {
|
||||
continue;
|
||||
@@ -281,6 +278,9 @@ final class ManagerRegler
|
||||
$rest -= $neuerSollwert - $ausgangswert;
|
||||
$sollwerte[$instanzID] = $neuerSollwert;
|
||||
}
|
||||
foreach ($gruppen as $gruppe) {
|
||||
self::verteilePositiveGruppe($gruppe, $sollwerte, $rest);
|
||||
}
|
||||
|
||||
$zugeteilt = $nichtSteuerbar;
|
||||
foreach ($steuerbar as $eintrag) {
|
||||
@@ -298,6 +298,95 @@ final class ManagerRegler
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array<string, mixed>> $gruppe Verbraucher derselben Prioritaet
|
||||
* @param array<int, int> $sollwerte
|
||||
*/
|
||||
private static function verteilePositiveGruppe(array $gruppe, array &$sollwerte, int &$rest): void
|
||||
{
|
||||
while ($rest > 0) {
|
||||
$kandidaten = self::naechsteLeistungsschritte($gruppe, $sollwerte, $rest);
|
||||
if ($kandidaten === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ganze Leistungsniveaus gemeinsam vergeben, ohne Bereiche Watt fuer Watt zu durchlaufen.
|
||||
$unten = $kandidaten[0]['NaechsteLeistung_W'] - 1;
|
||||
$oben = $unten;
|
||||
foreach ($kandidaten as $eintrag) {
|
||||
$oben = max($oben, $sollwerte[$eintrag['InstanzID']] + $rest);
|
||||
}
|
||||
while ($unten < $oben) {
|
||||
$mitte = $unten + intdiv($oben - $unten + 1, 2);
|
||||
$bedarf = 0;
|
||||
foreach ($kandidaten as $eintrag) {
|
||||
$bisher = $sollwerte[$eintrag['InstanzID']];
|
||||
$bedarf += max(0, self::groessterLeistungswertBis(
|
||||
$eintrag['Leistungswerte_W'],
|
||||
$mitte
|
||||
) - $bisher);
|
||||
if ($bedarf > $rest) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($bedarf <= $rest) {
|
||||
$unten = $mitte;
|
||||
} else {
|
||||
$oben = $mitte - 1;
|
||||
}
|
||||
}
|
||||
foreach ($kandidaten as $eintrag) {
|
||||
$id = $eintrag['InstanzID'];
|
||||
$neu = max($sollwerte[$id], self::groessterLeistungswertBis(
|
||||
$eintrag['Leistungswerte_W'],
|
||||
$unten
|
||||
));
|
||||
$rest -= $neu - $sollwerte[$id];
|
||||
$sollwerte[$id] = $neu;
|
||||
}
|
||||
|
||||
// Reicht es nicht fuer das ganze naechste Niveau, entscheidet Leistung, Energie, ID.
|
||||
$kandidaten = self::naechsteLeistungsschritte($gruppe, $sollwerte, $rest);
|
||||
if ($kandidaten === []) {
|
||||
return;
|
||||
}
|
||||
$erster = $kandidaten[0];
|
||||
$id = $erster['InstanzID'];
|
||||
$rest -= $erster['NaechsteLeistung_W'] - $sollwerte[$id];
|
||||
$sollwerte[$id] = $erster['NaechsteLeistung_W'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array<string, mixed>> $gruppe
|
||||
* @param array<int, int> $sollwerte
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private static function naechsteLeistungsschritte(array $gruppe, array $sollwerte, int $rest): array
|
||||
{
|
||||
$kandidaten = [];
|
||||
foreach ($gruppe as $eintrag) {
|
||||
$bisher = $sollwerte[$eintrag['InstanzID']];
|
||||
foreach ($eintrag['Leistungswerte_W'] as $angebot) {
|
||||
$naechste = is_int($angebot) ? $angebot : max($angebot['Von_W'], $bisher + 1);
|
||||
if ($naechste <= $bisher || (!is_int($angebot) && $naechste > $angebot['Bis_W'])) {
|
||||
continue;
|
||||
}
|
||||
if ($naechste - $bisher <= $rest) {
|
||||
$eintrag['NaechsteLeistung_W'] = $naechste;
|
||||
$kandidaten[] = $eintrag;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
usort($kandidaten, static function (array $links, array $rechts): int {
|
||||
return [$links['NaechsteLeistung_W'], $links['Energie_Wh'], $links['InstanzID']]
|
||||
<=> [$rechts['NaechsteLeistung_W'], $rechts['Energie_Wh'], $rechts['InstanzID']];
|
||||
});
|
||||
|
||||
return $kandidaten;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $daten
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user