625 lines
21 KiB
PHP
625 lines
21 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Belevo\EnelixEMS\Tests;
|
|
|
|
use Belevo\EnelixEMS\ManagerRegler;
|
|
use Belevo\EnelixEMS\Nachrichtenvertrag;
|
|
use InvalidArgumentException;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
final class ManagerReglerTest extends TestCase
|
|
{
|
|
public function testFahrplanVorgabeWirdZwischenPunktenLinearInterpoliert(): void
|
|
{
|
|
$punkte = [
|
|
['time' => '2026-09-30T11:35:00+00:00', 'gridTargetW' => 20486.254],
|
|
['time' => '2026-09-30T11:30:00+00:00', 'gridTargetW' => 15664.283],
|
|
];
|
|
|
|
$vorgabe = ManagerRegler::interpolierteFahrplanVorgabe(
|
|
$punkte,
|
|
(int) strtotime('2026-09-30T11:32:30+00:00')
|
|
);
|
|
|
|
self::assertEqualsWithDelta(18075.2685, $vorgabe, 0.0001);
|
|
}
|
|
|
|
public function testFahrplanVorgabeVerwendetRandpunktInnerhalbDerToleranz(): void
|
|
{
|
|
$punkte = [
|
|
['time' => '2026-09-30T11:30:00+00:00', 'gridTargetW' => 15664.283],
|
|
['time' => '2026-09-30T11:35:00+00:00', 'gridTargetW' => 20486.254],
|
|
];
|
|
|
|
self::assertSame(
|
|
15664.283,
|
|
ManagerRegler::interpolierteFahrplanVorgabe(
|
|
$punkte,
|
|
(int) strtotime('2026-09-30T11:29:44+00:00')
|
|
)
|
|
);
|
|
self::assertSame(
|
|
20486.254,
|
|
ManagerRegler::interpolierteFahrplanVorgabe(
|
|
$punkte,
|
|
(int) strtotime('2026-09-30T11:35:10+00:00')
|
|
)
|
|
);
|
|
}
|
|
|
|
public function testFahrplanVorgabeVerwirftZuGrosseZeitlicheLuecke(): void
|
|
{
|
|
$punkte = [
|
|
['time' => '2026-09-30T11:00:00+00:00', 'gridTargetW' => 10000],
|
|
['time' => '2026-09-30T12:00:00+00:00', 'gridTargetW' => 20000],
|
|
];
|
|
|
|
self::assertNull(
|
|
ManagerRegler::interpolierteFahrplanVorgabe(
|
|
$punkte,
|
|
(int) strtotime('2026-09-30T11:31:00+00:00')
|
|
)
|
|
);
|
|
}
|
|
|
|
public function testOhnePeakBegrenzungBleibtSolarladenAktiv(): void
|
|
{
|
|
self::assertSame(
|
|
ManagerRegler::BETRIEBSART_PV,
|
|
ManagerRegler::bestimmeBetriebsart(
|
|
true,
|
|
true,
|
|
25000.0,
|
|
ManagerRegler::BETRIEBSART_INAKTIV,
|
|
false,
|
|
0.0,
|
|
15000.0,
|
|
0.0
|
|
)
|
|
);
|
|
}
|
|
|
|
public function testBetriebsartBleibtZwischenDenZielwertenErhalten(): void
|
|
{
|
|
self::assertSame(
|
|
ManagerRegler::BETRIEBSART_PEAK,
|
|
ManagerRegler::bestimmeBetriebsart(
|
|
true,
|
|
true,
|
|
5000.0,
|
|
ManagerRegler::BETRIEBSART_PEAK,
|
|
true,
|
|
0.0,
|
|
12000.0,
|
|
0.0
|
|
)
|
|
);
|
|
}
|
|
|
|
public function testUmschaltdifferenzVerhindertZuKleineAenderung(): void
|
|
{
|
|
self::assertSame(
|
|
ManagerRegler::BETRIEBSART_PV,
|
|
ManagerRegler::bestimmeBetriebsart(
|
|
true,
|
|
true,
|
|
11000.0,
|
|
ManagerRegler::BETRIEBSART_PV,
|
|
true,
|
|
10000.0,
|
|
10500.0,
|
|
60.0
|
|
)
|
|
);
|
|
}
|
|
|
|
public function testWechseltOberhalbDerPeakgrenzeInDenPeakbetrieb(): void
|
|
{
|
|
self::assertSame(
|
|
ManagerRegler::BETRIEBSART_PEAK,
|
|
ManagerRegler::bestimmeBetriebsart(
|
|
true,
|
|
true,
|
|
12500.0,
|
|
ManagerRegler::BETRIEBSART_PV,
|
|
true,
|
|
0.0,
|
|
12000.0,
|
|
5.0
|
|
)
|
|
);
|
|
}
|
|
|
|
public function testWechseltUnterhalbDesSolarsollwertsInDenPvBetrieb(): void
|
|
{
|
|
self::assertSame(
|
|
ManagerRegler::BETRIEBSART_PV,
|
|
ManagerRegler::bestimmeBetriebsart(
|
|
true,
|
|
true,
|
|
-500.0,
|
|
ManagerRegler::BETRIEBSART_PEAK,
|
|
true,
|
|
0.0,
|
|
12000.0,
|
|
5.0
|
|
)
|
|
);
|
|
}
|
|
|
|
public function testVerteilungBeruecksichtigtPrioritaetEinzelwerteUndBereiche(): void
|
|
{
|
|
$ergebnis = ManagerRegler::verteile(
|
|
0.0,
|
|
4500.0,
|
|
[
|
|
$this->verbraucher(20, 5, [0, 3000], 0),
|
|
$this->verbraucher(10, 0, [0, ['Von_W' => 1000, 'Bis_W' => 2000], 4000], 0),
|
|
],
|
|
'PrioritaetPV'
|
|
);
|
|
|
|
self::assertSame(4500, $ergebnis['Verteilbudget_W']);
|
|
self::assertSame([10 => 4000, 20 => 0], $ergebnis['Sollwerte']);
|
|
self::assertSame(500, $ergebnis['Restabweichung_W']);
|
|
}
|
|
|
|
public function testGleicheNaechsteLeistungBevorzugtWenigerEnergie(): void
|
|
{
|
|
$ergebnis = ManagerRegler::verteile(
|
|
0.0,
|
|
3000.0,
|
|
[
|
|
$this->verbraucher(10, 0, [0, 3000], 0),
|
|
$this->verbraucher(20, 0, [0, 3000], 0),
|
|
],
|
|
'PrioritaetPV',
|
|
[10 => 3000.0, 20 => 0.0]
|
|
);
|
|
|
|
self::assertSame([20 => 3000, 10 => 0], $ergebnis['Sollwerte']);
|
|
self::assertSame(0, $ergebnis['Restabweichung_W']);
|
|
}
|
|
|
|
public function testEnergiegleichstandVergleichtExakteWhStattZweiKilowattstundenGruppen(): void
|
|
{
|
|
$ergebnis = ManagerRegler::verteile(
|
|
0.0,
|
|
3000.0,
|
|
[
|
|
$this->verbraucher(10, 0, [0, 3000], 0),
|
|
$this->verbraucher(20, 0, [0, 3000], 0),
|
|
],
|
|
'PrioritaetPV',
|
|
[10 => 999.0, 20 => 0.0]
|
|
);
|
|
|
|
self::assertSame([10 => 0, 20 => 3000], $ergebnis['Sollwerte']);
|
|
}
|
|
|
|
/** @dataProvider beispielBudgets */
|
|
public function testBestaetigteStufenfolge(int $budget, int $a, int $b): void
|
|
{
|
|
foreach (['PrioritaetPV', 'PrioritaetPeak'] as $feld) {
|
|
$ergebnis = ManagerRegler::verteile(0.0, (float) $budget, [
|
|
$this->verbraucher(20, 2, [0, 100, 110, 500, 780, 1500], 0),
|
|
$this->verbraucher(10, 2, [0, 100, 200, 400, 800], 0),
|
|
], $feld, [10 => 10000.0, 20 => 12000.0]);
|
|
|
|
self::assertSame([10 => $a, 20 => $b], $ergebnis['Sollwerte']);
|
|
self::assertSame($budget - $a - $b, $ergebnis['Restabweichung_W']);
|
|
}
|
|
}
|
|
|
|
public function beispielBudgets(): array
|
|
{
|
|
return [
|
|
[0, 0, 0], [99, 0, 0], [100, 100, 0], [199, 100, 0],
|
|
[200, 100, 100], [209, 100, 100], [210, 100, 110],
|
|
[309, 100, 110], [310, 200, 110], [509, 200, 110],
|
|
[510, 400, 110], [899, 400, 110], [900, 400, 500],
|
|
[1179, 400, 500], [1180, 400, 780], [1579, 400, 780],
|
|
[1580, 800, 780], [2299, 800, 780], [2300, 800, 1500],
|
|
[3000, 800, 1500],
|
|
];
|
|
}
|
|
|
|
public function testLeistungsniveauGehtVorEnergieUndSchrittdifferenz(): void
|
|
{
|
|
$ergebnis = ManagerRegler::verteile(0.0, 220.0, [
|
|
$this->verbraucher(10, 0, [0, 100, 200], 0),
|
|
$this->verbraucher(20, 0, [0, 110, 120], 0),
|
|
], 'PrioritaetPV', [10 => 0.0, 20 => 50000.0]);
|
|
|
|
self::assertSame([10 => 100, 20 => 120], $ergebnis['Sollwerte']);
|
|
}
|
|
|
|
public function testPicoUndGoETeilenBudgetTrotzGrossemEnergieunterschied(): void
|
|
{
|
|
$ergebnis = ManagerRegler::verteile(0.0, 12312.0, [
|
|
$this->verbraucher(31986, 2, array_merge([0], range(4104, 12312, 684)), 0),
|
|
$this->verbraucher(43878, 2, array_merge([0], range(4104, 10944, 684)), 0),
|
|
], 'PrioritaetPV', [31986 => 41192.78, 43878 => 128082.87]);
|
|
|
|
self::assertSame([31986 => 6156, 43878 => 6156], $ergebnis['Sollwerte']);
|
|
self::assertSame(0, $ergebnis['Restabweichung_W']);
|
|
}
|
|
|
|
public function testNegativeDefizitverteilungBehaeltBisherigeEnergiegruppen(): void
|
|
{
|
|
$ergebnis = ManagerRegler::verteile(300.0, 0.0, [
|
|
$this->verbraucher(10, 0, [['Von_W' => -300, 'Bis_W' => 300]], 0),
|
|
$this->verbraucher(20, 0, [['Von_W' => -300, 'Bis_W' => 300]], 0),
|
|
], 'PrioritaetPeak', [10 => 999.0, 20 => 0.0]);
|
|
|
|
self::assertSame([10 => -300, 20 => 0], $ergebnis['Sollwerte']);
|
|
self::assertSame(0, $ergebnis['Restabweichung_W']);
|
|
}
|
|
|
|
public function testGleicheLeistungUndEnergieEntscheidetStabilNachInstanzID(): void
|
|
{
|
|
$ergebnis = ManagerRegler::verteile(0.0, 100.0, [
|
|
$this->verbraucher(20, 0, [0, 100], 0),
|
|
$this->verbraucher(10, 0, [0, 100], 0),
|
|
], 'PrioritaetPV');
|
|
|
|
self::assertSame([10 => 100, 20 => 0], $ergebnis['Sollwerte']);
|
|
}
|
|
|
|
public function testNichtPassenderSchrittBlockiertKeineAndereErreichbareStufe(): void
|
|
{
|
|
$ergebnis = ManagerRegler::verteile(0.0, 210.0, [
|
|
$this->verbraucher(10, 0, [0, 100, 200], 0),
|
|
$this->verbraucher(20, 0, [0, 150], 0),
|
|
], 'PrioritaetPV');
|
|
|
|
self::assertSame([10 => 200, 20 => 0], $ergebnis['Sollwerte']);
|
|
self::assertSame(10, $ergebnis['Restabweichung_W']);
|
|
}
|
|
|
|
public function testPeakVerwendetPeakPrioritaetVorLeistungUndEnergie(): void
|
|
{
|
|
$a = $this->verbraucher(10, 0, [0, 100, 200], 0);
|
|
$b = $this->verbraucher(20, 9, [0, 300], 0);
|
|
$a['Daten']['PrioritaetPeak'] = 9;
|
|
$b['Daten']['PrioritaetPeak'] = 0;
|
|
$ergebnis = ManagerRegler::verteile(0.0, 300.0, [$a, $b], 'PrioritaetPeak', [20 => 50000.0]);
|
|
|
|
self::assertSame([20 => 300, 10 => 0], $ergebnis['Sollwerte']);
|
|
}
|
|
|
|
public function testGrosseBereicheWerdenGemeinsamOhneWattweiseSchleifeVerteilt(): void
|
|
{
|
|
$ergebnis = ManagerRegler::verteile(0.0, 1000000001.0, [
|
|
$this->verbraucher(10, 0, [['Von_W' => 0, 'Bis_W' => 1000000000]], 0),
|
|
$this->verbraucher(20, 0, [['Von_W' => 0, 'Bis_W' => 1000000000]], 0),
|
|
], 'PrioritaetPV', [10 => 999.0, 20 => 0.0]);
|
|
|
|
self::assertSame([10 => 500000000, 20 => 500000001], $ergebnis['Sollwerte']);
|
|
self::assertSame(0, $ergebnis['Restabweichung_W']);
|
|
}
|
|
|
|
public function testBereicheUndEinzelwerteGegenWattweiseReferenz(): void
|
|
{
|
|
$angebote = [
|
|
[0, ['Von_W' => 3, 'Bis_W' => 9], 15],
|
|
[0, 5, ['Von_W' => 7, 'Bis_W' => 12], 18],
|
|
[0, 4, 8, ['Von_W' => 14, 'Bis_W' => 20]],
|
|
];
|
|
$energien = [10 => 10000.5, 20 => 10000.0, 30 => 10000.0];
|
|
$verbraucher = [];
|
|
$diskret = [];
|
|
foreach ($angebote as $index => $angebot) {
|
|
$id = ($index + 1) * 10;
|
|
$verbraucher[] = $this->verbraucher($id, 2, $angebot, 0);
|
|
$diskret[$id] = [];
|
|
foreach ($angebot as $wert) {
|
|
foreach (is_int($wert) ? [$wert] : range($wert['Von_W'], $wert['Bis_W']) as $watt) {
|
|
$diskret[$id][] = $watt;
|
|
}
|
|
}
|
|
}
|
|
for ($budget = 0; $budget <= 60; $budget++) {
|
|
$erwartet = [10 => 0, 20 => 0, 30 => 0];
|
|
$rest = $budget;
|
|
while (true) {
|
|
$schritte = [];
|
|
foreach ($diskret as $id => $werte) {
|
|
foreach ($werte as $wert) {
|
|
if ($wert > $erwartet[$id]) {
|
|
if ($wert - $erwartet[$id] <= $rest) {
|
|
$schritte[] = [$wert, $energien[$id], $id];
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ($schritte === []) {
|
|
break;
|
|
}
|
|
sort($schritte);
|
|
[$wert, , $id] = $schritte[0];
|
|
$rest -= $wert - $erwartet[$id];
|
|
$erwartet[$id] = $wert;
|
|
}
|
|
$ergebnis = ManagerRegler::verteile(0.0, (float) $budget, array_reverse($verbraucher),
|
|
'PrioritaetPV', $energien);
|
|
$ist = $ergebnis['Sollwerte'];
|
|
ksort($ist);
|
|
self::assertSame($erwartet, $ist, 'Budget: ' . $budget);
|
|
self::assertSame($rest, $ergebnis['Restabweichung_W']);
|
|
}
|
|
}
|
|
|
|
public function testNichtVerfuegbareLastWirdReserviertUndNichtNeuZugeteilt(): void
|
|
{
|
|
$a = $this->verbraucher(10, 0, [0, 100, 200], 100);
|
|
$a['Daten']['Verfuegbar'] = false;
|
|
$ergebnis = ManagerRegler::verteile(100.0, 200.0, [
|
|
$a,
|
|
$this->verbraucher(20, 0, [0, 100, 200], 0),
|
|
], 'PrioritaetPV');
|
|
|
|
self::assertSame(100, $ergebnis['NichtSteuerbar_W']);
|
|
self::assertSame([20 => 100], $ergebnis['Sollwerte']);
|
|
}
|
|
|
|
public function testFestwertWirdUnabhaengigVonAenderungMoeglichZugewiesen(): void
|
|
{
|
|
$fest = $this->verbraucher(10, 0, [3000], 3000, false);
|
|
$steuerbar = $this->verbraucher(20, 1, [0, ['Von_W' => 1, 'Bis_W' => 4000]], 0);
|
|
|
|
$ergebnis = ManagerRegler::verteile(3000.0, 5000.0, [$fest, $steuerbar], 'PrioritaetPV');
|
|
|
|
self::assertSame(3000, $ergebnis['NichtSteuerbar_W']);
|
|
self::assertSame([10 => 3000, 20 => 2000], $ergebnis['Sollwerte']);
|
|
self::assertSame(0, $ergebnis['Restabweichung_W']);
|
|
}
|
|
|
|
public function testFestwerteWerdenNachIstleistungBilanziertUndAlsBefehlBeibehalten(): void
|
|
{
|
|
$ergebnis = ManagerRegler::verteile(
|
|
-2411.0,
|
|
0.0,
|
|
[
|
|
$this->verbraucher(
|
|
44234,
|
|
0,
|
|
[['Von_W' => -39000, 'Bis_W' => 39000]],
|
|
0
|
|
),
|
|
$this->verbraucher(38676, 1, [0, 4600], 0),
|
|
$this->verbraucher(29743, 1, [0, 6500], 0),
|
|
$this->verbraucher(43878, 2, [13850], 10151, false),
|
|
$this->verbraucher(46052, 2, [11000], 0, false),
|
|
],
|
|
'PrioritaetPV'
|
|
);
|
|
|
|
self::assertSame(12562, $ergebnis['Verteilbudget_W']);
|
|
self::assertSame(10151, $ergebnis['NichtSteuerbar_W']);
|
|
self::assertSame(
|
|
[
|
|
44234 => 2411,
|
|
29743 => 0,
|
|
38676 => 0,
|
|
43878 => 13850,
|
|
46052 => 11000,
|
|
],
|
|
$ergebnis['Sollwerte']
|
|
);
|
|
self::assertSame(0, $ergebnis['Restabweichung_W']);
|
|
}
|
|
|
|
public function testBatterieGleichtGemesseneFesteLastenAusOhneSolarladungZuSpeisen(): 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(10942, $ergebnis['NichtSteuerbar_W']);
|
|
self::assertSame(
|
|
[
|
|
29743 => 0,
|
|
38676 => 0,
|
|
22078 => 7690,
|
|
31986 => 11000,
|
|
43878 => 0,
|
|
44234 => 2715,
|
|
],
|
|
$ergebnis['Sollwerte']
|
|
);
|
|
self::assertSame(0, $ergebnis['Restabweichung_W']);
|
|
}
|
|
|
|
public function testBegrenztesFahrzeugLaedtVorBatterieOhneBatterieentladung(): void
|
|
{
|
|
$ergebnis = ManagerRegler::verteile(
|
|
-3587.0,
|
|
0.0,
|
|
[
|
|
$this->verbraucher(
|
|
10,
|
|
0,
|
|
[0, 4150, 4850, 5550, 6250, 6950, 7600, 8300, 9000, 9700, 10300, 11000],
|
|
10263
|
|
),
|
|
$this->verbraucher(
|
|
20,
|
|
1,
|
|
[['Von_W' => -39000, 'Bis_W' => 39000]],
|
|
0
|
|
),
|
|
],
|
|
'PrioritaetPV'
|
|
);
|
|
|
|
self::assertSame(13850, $ergebnis['Verteilbudget_W']);
|
|
self::assertSame([10 => 11000, 20 => 2850], $ergebnis['Sollwerte']);
|
|
self::assertGreaterThanOrEqual(0, $ergebnis['Sollwerte'][20]);
|
|
self::assertSame(0, $ergebnis['Restabweichung_W']);
|
|
}
|
|
|
|
public function testPvBetriebNutztBeiPositivemBudgetKeineNegativeLeistungsstufe(): void
|
|
{
|
|
$ergebnis = ManagerRegler::verteile(
|
|
0.0,
|
|
500.0,
|
|
[
|
|
$this->verbraucher(10, 0, [-1000, 5000], 0),
|
|
$this->verbraucher(20, 1, [0, 3000], 0),
|
|
],
|
|
'PrioritaetPV'
|
|
);
|
|
|
|
self::assertSame(500, $ergebnis['Verteilbudget_W']);
|
|
self::assertSame([10 => 5000, 20 => 0], $ergebnis['Sollwerte']);
|
|
self::assertGreaterThanOrEqual(0, $ergebnis['Sollwerte'][10]);
|
|
self::assertSame(-4500, $ergebnis['Restabweichung_W']);
|
|
}
|
|
|
|
public function testPvBetriebNutztNegativeLeistungErstBeiTatsaechlichemDefizit(): void
|
|
{
|
|
$ergebnis = ManagerRegler::verteile(
|
|
1000.0,
|
|
0.0,
|
|
[
|
|
$this->verbraucher(
|
|
10,
|
|
0,
|
|
[['Von_W' => -5000, 'Bis_W' => 5000]],
|
|
0
|
|
),
|
|
$this->verbraucher(20, 1, [0, 3000], 0),
|
|
],
|
|
'PrioritaetPV'
|
|
);
|
|
|
|
self::assertSame(-1000, $ergebnis['Verteilbudget_W']);
|
|
self::assertSame([10 => -1000, 20 => 0], $ergebnis['Sollwerte']);
|
|
self::assertSame(0, $ergebnis['Restabweichung_W']);
|
|
}
|
|
|
|
public function testFestgehaltenerVerbraucherBilanziertIstUndBehaeltSollwert(): void
|
|
{
|
|
$festgehalten = $this->verbraucher(10, 0, [0, 3000, 5000], 2000, false);
|
|
$festgehalten['Daten']['Zustand'][0]['Wert'] = 3000;
|
|
|
|
$ergebnis = ManagerRegler::verteile(
|
|
0.0,
|
|
3000.0,
|
|
[
|
|
$festgehalten,
|
|
$this->verbraucher(20, 1, [['Von_W' => 0, 'Bis_W' => 5000]], 0),
|
|
],
|
|
'PrioritaetPV'
|
|
);
|
|
|
|
self::assertSame(5000, $ergebnis['Verteilbudget_W']);
|
|
self::assertSame(2000, $ergebnis['NichtSteuerbar_W']);
|
|
self::assertSame([10 => 3000, 20 => 3000], $ergebnis['Sollwerte']);
|
|
self::assertSame(0, $ergebnis['Restabweichung_W']);
|
|
}
|
|
|
|
public function testFehlendeIstleistungFaelltAufAngenommenenSollwertZurueck(): void
|
|
{
|
|
$verbraucher = $this->verbraucher(10, 0, [3000], null, false);
|
|
$verbraucher['Daten']['Leistungsquelle'] = Nachrichtenvertrag::LEISTUNGSQUELLE_NICHT_VORHANDEN;
|
|
$verbraucher['Daten']['Istleistung_W'] = null;
|
|
$verbraucher['Daten']['Zustand'][0]['Wert'] = 3000;
|
|
|
|
$ergebnis = ManagerRegler::verteile(3000.0, 0.0, [$verbraucher], 'PrioritaetPV');
|
|
|
|
self::assertSame(3000, $ergebnis['AktuelleVerbraucherleistung_W']);
|
|
self::assertSame([10 => 3000], $ergebnis['Sollwerte']);
|
|
self::assertSame(-3000, $ergebnis['Restabweichung_W']);
|
|
}
|
|
|
|
public function testBatterieMitTieferPrioritaetUebernimmtNichtNutzbarenRest(): void
|
|
{
|
|
$ergebnis = ManagerRegler::verteile(
|
|
-5000.0,
|
|
0.0,
|
|
[
|
|
$this->verbraucher(20, 1, [0, 3000, 6000], 0),
|
|
$this->verbraucher(
|
|
10,
|
|
6,
|
|
[['Von_W' => 0, 'Bis_W' => 10000]],
|
|
0
|
|
),
|
|
],
|
|
'PrioritaetPV'
|
|
);
|
|
|
|
self::assertSame([20 => 3000, 10 => 2000], $ergebnis['Sollwerte']);
|
|
self::assertSame(0, $ergebnis['Restabweichung_W']);
|
|
}
|
|
|
|
public function testMonatlicheGrenzeMussVollstaendigSein(): void
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
ManagerRegler::wirksameLastspitzengrenze(2, 0.0, [1 => 12000.0], 9);
|
|
}
|
|
|
|
/**
|
|
* @param list<int|array{Von_W: int, Bis_W: int}> $leistungswerte
|
|
* @return array{InstanzID: int, Daten: array<string, mixed>}
|
|
*/
|
|
private function verbraucher(
|
|
int $instanzID,
|
|
int $prioritaet,
|
|
array $leistungswerte,
|
|
?int $istleistung,
|
|
bool $aenderungMoeglich = true
|
|
): array {
|
|
$quelle = $istleistung === null
|
|
? Nachrichtenvertrag::LEISTUNGSQUELLE_NICHT_VORHANDEN
|
|
: Nachrichtenvertrag::LEISTUNGSQUELLE_GEMESSEN;
|
|
|
|
return [
|
|
'InstanzID' => $instanzID,
|
|
'Daten' => [
|
|
'Kopf' => [
|
|
'Version' => Nachrichtenvertrag::VERSION,
|
|
'AbsenderID' => $instanzID,
|
|
'EmpfaengerID' => 1,
|
|
'Zeitpunkt' => 1788825600,
|
|
],
|
|
'Betriebsart' => Nachrichtenvertrag::BETRIEBSART_PV,
|
|
'PrioritaetPV' => $prioritaet,
|
|
'PrioritaetPeak' => $prioritaet,
|
|
'Leistungswerte_W' => $leistungswerte,
|
|
'AenderungMoeglich' => $aenderungMoeglich,
|
|
'Verfuegbar' => true,
|
|
'Istleistung_W' => $istleistung,
|
|
'Leistungsquelle' => $quelle,
|
|
'Zustand' => [[
|
|
'Kennung' => 'Sollleistung_W',
|
|
'Art' => 'Sollwert',
|
|
'Wert' => $istleistung,
|
|
'Einheit' => 'W',
|
|
]],
|
|
],
|
|
];
|
|
}
|
|
}
|