167 lines
5.4 KiB
PHP
167 lines
5.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Belevo\EnelixEMS;
|
|
|
|
use DateTimeImmutable;
|
|
use DateTimeZone;
|
|
use InvalidArgumentException;
|
|
|
|
final class EinStufigRegler
|
|
{
|
|
/**
|
|
* @return list<int>
|
|
*/
|
|
public static function leistungsangebot(
|
|
int $nennleistung,
|
|
int $istleistung,
|
|
bool $verfuegbar,
|
|
bool $aenderungMoeglich,
|
|
bool $mindestlaufzeitErzwungen
|
|
): array {
|
|
if ($nennleistung <= 0) {
|
|
throw new InvalidArgumentException('Die Nennleistung muss groesser als 0 sein.');
|
|
}
|
|
if (!in_array($istleistung, [0, $nennleistung], true)) {
|
|
throw new InvalidArgumentException('Die Istleistung muss 0 oder der Nennleistung entsprechen.');
|
|
}
|
|
|
|
if (!$verfuegbar || !$aenderungMoeglich || $mindestlaufzeitErzwungen) {
|
|
return [$istleistung];
|
|
}
|
|
|
|
return [0, $nennleistung];
|
|
}
|
|
|
|
public static function freigabezeitpunkt(
|
|
bool $eingeschaltet,
|
|
int $bestaetigtSeit,
|
|
int $mindesteinschaltdauer,
|
|
int $mindestausschaltdauer
|
|
): int {
|
|
if ($bestaetigtSeit < 0 || $mindesteinschaltdauer < 0 || $mindestausschaltdauer < 0) {
|
|
throw new InvalidArgumentException('Zeitwerte duerfen nicht negativ sein.');
|
|
}
|
|
|
|
return $bestaetigtSeit + ($eingeschaltet ? $mindesteinschaltdauer : $mindestausschaltdauer);
|
|
}
|
|
|
|
public static function restMindestzeit(int $freigabezeitpunkt, int $jetzt): int
|
|
{
|
|
if ($freigabezeitpunkt < 0 || $jetzt < 0) {
|
|
throw new InvalidArgumentException('Zeitwerte duerfen nicht negativ sein.');
|
|
}
|
|
|
|
return max(0, $freigabezeitpunkt - $jetzt);
|
|
}
|
|
|
|
public static function mussMindestlaufzeitErzwingen(
|
|
int $tageslaufzeit,
|
|
int $mindestlaufzeit,
|
|
int $sekundenBisTagesende
|
|
): bool {
|
|
self::pruefeLaufzeiten($tageslaufzeit, $mindestlaufzeit, $sekundenBisTagesende);
|
|
|
|
$restlaufzeit = max(0, $mindestlaufzeit - $tageslaufzeit);
|
|
|
|
return $restlaufzeit > 0 && $sekundenBisTagesende <= $restlaufzeit;
|
|
}
|
|
|
|
public static function sekundenBisNaechsteTagespruefung(
|
|
int $tageslaufzeit,
|
|
int $mindestlaufzeit,
|
|
int $sekundenBisTagesende,
|
|
bool $eingeschaltet
|
|
): int {
|
|
self::pruefeLaufzeiten($tageslaufzeit, $mindestlaufzeit, $sekundenBisTagesende);
|
|
|
|
$restlaufzeit = max(0, $mindestlaufzeit - $tageslaufzeit);
|
|
if ($restlaufzeit === 0) {
|
|
return max(1, $sekundenBisTagesende);
|
|
}
|
|
if ($eingeschaltet) {
|
|
return max(1, min($restlaufzeit, $sekundenBisTagesende));
|
|
}
|
|
|
|
return max(1, $sekundenBisTagesende - $restlaufzeit);
|
|
}
|
|
|
|
/**
|
|
* @return array{Tag: string, Sekunden: int, StandZeit: int}
|
|
*/
|
|
public static function aktualisiereTageslaufzeit(
|
|
string $gespeicherterTag,
|
|
int $gespeicherteSekunden,
|
|
int $standZeit,
|
|
int $jetzt,
|
|
bool $warEingeschaltet,
|
|
DateTimeZone $zeitzone
|
|
): array {
|
|
if ($gespeicherteSekunden < 0 || $standZeit < 0 || $jetzt < 0) {
|
|
throw new InvalidArgumentException('Zeitwerte duerfen nicht negativ sein.');
|
|
}
|
|
|
|
$jetztDatum = self::datum($jetzt, $zeitzone);
|
|
$aktuellerTag = $jetztDatum->format('Y-m-d');
|
|
if ($standZeit <= 0 || $standZeit > $jetzt) {
|
|
return [
|
|
'Tag' => $aktuellerTag,
|
|
'Sekunden' => $gespeicherterTag === $aktuellerTag ? $gespeicherteSekunden : 0,
|
|
'StandZeit' => $jetzt,
|
|
];
|
|
}
|
|
|
|
$standDatum = self::datum($standZeit, $zeitzone);
|
|
$sekunden = $gespeicherteSekunden;
|
|
if ($gespeicherterTag !== $aktuellerTag || $standDatum->format('Y-m-d') !== $aktuellerTag) {
|
|
$sekunden = 0;
|
|
if ($warEingeschaltet) {
|
|
$tagesbeginn = $jetztDatum->setTime(0, 0)->getTimestamp();
|
|
$sekunden = max(0, $jetzt - max($standZeit, $tagesbeginn));
|
|
}
|
|
} elseif ($warEingeschaltet) {
|
|
$sekunden += $jetzt - $standZeit;
|
|
}
|
|
|
|
$tagesbeginn = $jetztDatum->setTime(0, 0);
|
|
$tagesdauer = $tagesbeginn->modify('+1 day')->getTimestamp() - $tagesbeginn->getTimestamp();
|
|
|
|
return [
|
|
'Tag' => $aktuellerTag,
|
|
'Sekunden' => min($sekunden, $tagesdauer),
|
|
'StandZeit' => $jetzt,
|
|
];
|
|
}
|
|
|
|
public static function sekundenBisTagesende(int $jetzt, DateTimeZone $zeitzone): int
|
|
{
|
|
if ($jetzt < 0) {
|
|
throw new InvalidArgumentException('Der Zeitpunkt darf nicht negativ sein.');
|
|
}
|
|
|
|
$datum = self::datum($jetzt, $zeitzone);
|
|
$tagesende = $datum->setTime(0, 0)->modify('+1 day');
|
|
|
|
return max(1, $tagesende->getTimestamp() - $jetzt);
|
|
}
|
|
|
|
private static function pruefeLaufzeiten(
|
|
int $tageslaufzeit,
|
|
int $mindestlaufzeit,
|
|
int $sekundenBisTagesende
|
|
): void {
|
|
if ($tageslaufzeit < 0 || $mindestlaufzeit < 0 || $mindestlaufzeit > 86400) {
|
|
throw new InvalidArgumentException('Laufzeiten sind ausserhalb des gueltigen Bereichs.');
|
|
}
|
|
if ($sekundenBisTagesende <= 0) {
|
|
throw new InvalidArgumentException('Sekunden bis Tagesende muss groesser als 0 sein.');
|
|
}
|
|
}
|
|
|
|
private static function datum(int $zeitpunkt, DateTimeZone $zeitzone): DateTimeImmutable
|
|
{
|
|
return (new DateTimeImmutable('@' . $zeitpunkt))->setTimezone($zeitzone);
|
|
}
|
|
}
|