Files
Enelix-EMS/libs/EinStufigRegler.php
T
2026-09-17 09:32:17 +00:00

145 lines
4.6 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 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);
}
}