@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Belevo\EnelixUtils\Energiediagramm;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use DateTimeZone;
|
||||
use InvalidArgumentException;
|
||||
|
||||
final class EnergyChartCalculator
|
||||
{
|
||||
public const RANGES = ['day', 'week', 'month', 'year', 'total', 'custom'];
|
||||
|
||||
public static function isValidDate(string $date): bool
|
||||
{
|
||||
$value = DateTimeImmutable::createFromFormat('!Y-m-d', $date);
|
||||
$errors = DateTimeImmutable::getLastErrors();
|
||||
|
||||
return $value !== false
|
||||
&& ($errors === false || ($errors['warning_count'] === 0 && $errors['error_count'] === 0))
|
||||
&& $value->format('Y-m-d') === $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{0: int, 1: int}
|
||||
*/
|
||||
public static function rangeBounds(
|
||||
string $range,
|
||||
string $date,
|
||||
string $customStart,
|
||||
string $customEnd,
|
||||
?int $now = null
|
||||
): array {
|
||||
if (!in_array($range, self::RANGES, true)) {
|
||||
throw new InvalidArgumentException('Unbekannter Zeitraum.');
|
||||
}
|
||||
|
||||
$now ??= time();
|
||||
if ($range === 'total') {
|
||||
return [0, $now];
|
||||
}
|
||||
|
||||
if ($range === 'custom') {
|
||||
$start = self::date($customStart);
|
||||
$end = self::date($customEnd);
|
||||
if ($start > $end) {
|
||||
throw new InvalidArgumentException('Das Startdatum liegt nach dem Enddatum.');
|
||||
}
|
||||
|
||||
return [$start->getTimestamp(), $end->modify('+1 day')->getTimestamp()];
|
||||
}
|
||||
|
||||
$base = self::date($date);
|
||||
switch ($range) {
|
||||
case 'day':
|
||||
$start = $base;
|
||||
$end = $start->modify('+1 day');
|
||||
break;
|
||||
case 'week':
|
||||
$start = $base->modify('monday this week');
|
||||
$end = $start->modify('+1 week');
|
||||
break;
|
||||
case 'month':
|
||||
$start = $base->modify('first day of this month');
|
||||
$end = $start->modify('first day of next month');
|
||||
break;
|
||||
case 'year':
|
||||
$start = $base->setDate((int) $base->format('Y'), 1, 1);
|
||||
$end = $start->modify('+1 year');
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException('Unbekannter Zeitraum.');
|
||||
}
|
||||
|
||||
return [$start->getTimestamp(), $end->getTimestamp()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{
|
||||
* Produktion: float,
|
||||
* Einspeisung: float,
|
||||
* Netzbezug: float,
|
||||
* Hausverbrauch: float,
|
||||
* Eigenverbrauch: float,
|
||||
* Eigenverbrauchsquote: float,
|
||||
* Autarkiegrad: float
|
||||
* }
|
||||
*/
|
||||
public static function metrics(
|
||||
float $production,
|
||||
float $feedIn,
|
||||
float $grid,
|
||||
?float $consumption = null
|
||||
): array {
|
||||
$production = max(0.0, $production);
|
||||
$feedIn = max(0.0, $feedIn);
|
||||
$grid = max(0.0, $grid);
|
||||
$house = $consumption === null
|
||||
? max(0.0, $production - $feedIn + $grid)
|
||||
: max(0.0, $consumption);
|
||||
$selfConsumption = min($production, max(0.0, $house - $grid));
|
||||
|
||||
return [
|
||||
'Produktion' => $production,
|
||||
'Einspeisung' => $feedIn,
|
||||
'Netzbezug' => $grid,
|
||||
'Hausverbrauch' => $house,
|
||||
'Eigenverbrauch' => $selfConsumption,
|
||||
'Eigenverbrauchsquote' => $production > 0.0
|
||||
? min(100.0, ($selfConsumption / $production) * 100.0)
|
||||
: 0.0,
|
||||
'Autarkiegrad' => $house > 0.0
|
||||
? min(100.0, ($selfConsumption / $house) * 100.0)
|
||||
: 0.0,
|
||||
];
|
||||
}
|
||||
|
||||
public static function normalizeColor(string $color, string $fallback): string
|
||||
{
|
||||
return preg_match('/^#[0-9A-Fa-f]{6}$/', $color) === 1
|
||||
? strtoupper($color)
|
||||
: strtoupper($fallback);
|
||||
}
|
||||
|
||||
private static function date(string $date): DateTimeImmutable
|
||||
{
|
||||
if (!self::isValidDate($date)) {
|
||||
throw new InvalidArgumentException('Ungültiges Datum.');
|
||||
}
|
||||
|
||||
return new DateTimeImmutable($date . ' 00:00:00', new DateTimeZone(date_default_timezone_get()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user