Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/Domain/Dashboard/StatsContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ enum StatsContext: string implements TranslatableInterface
case MOVING_TIME = 'movingTime';
case DISTANCE = 'distance';
case ELEVATION = 'elevation';
case LOAD = 'load';

public function trans(TranslatorInterface $translator, ?string $locale = null): string
{
return match ($this) {
self::MOVING_TIME => $translator->trans('Time', locale: $locale),
self::DISTANCE => $translator->trans('Distance', locale: $locale),
self::ELEVATION => $translator->trans('Elevation', locale: $locale),
self::LOAD => $translator->trans('Load', locale: $locale),
};
}

Expand All @@ -28,13 +30,27 @@ public function getSvgIcon(): string
self::MOVING_TIME => 'time',
self::DISTANCE => 'distance',
self::ELEVATION => 'elevation',
self::LOAD => 'load',
};
}

/**
* @return StatsContext[]
*/
public static function defaultSortingOrder(): array
{
return [
self::DISTANCE,
self::MOVING_TIME,
self::ELEVATION,
self::LOAD,
];
}

/**
* @return StatsContext[]
*/
public static function defaultChartSortingOrder(): array
{
return [
self::DISTANCE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function getDefaultConfiguration(): WidgetConfiguration
{
return WidgetConfiguration::empty()
->add('enableLastXYearsByDefault', 10)
->add('metricsDisplayOrder', array_map(fn (StatsContext $context) => $context->value, StatsContext::defaultSortingOrder()));
->add('metricsDisplayOrder', array_map(fn (StatsContext $context) => $context->value, StatsContext::defaultChartSortingOrder()));
}

public function guardValidConfiguration(WidgetConfiguration $configuration): void
Expand Down Expand Up @@ -68,7 +68,7 @@ public function render(SerializableDateTime $now, WidgetConfiguration $configura

/** @var int $enableLastXYearsByDefault */
$enableLastXYearsByDefault = $configuration->get('enableLastXYearsByDefault');
foreach (StatsContext::cases() as $monthlyStatsContext) {
foreach (StatsContext::defaultChartSortingOrder() as $monthlyStatsContext) {
foreach ($activityTypes as $activityType) {
if (in_array($monthlyStatsContext, [StatsContext::DISTANCE, StatsContext::ELEVATION]) && !$activityType->supportsDistanceAndElevation()) {
continue;
Expand Down
23 changes: 21 additions & 2 deletions src/Domain/Dashboard/Widget/WeeklyStats/WeeklyStatsChart.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Domain\Activity\Activities;
use App\Domain\Activity\Activity;
use App\Domain\Activity\ActivityType;
use App\Domain\Activity\DailyTrainingLoad;
use App\Domain\Calendar\Week;
use App\Domain\Calendar\Weeks;
use App\Domain\Dashboard\StatsContext;
Expand All @@ -18,6 +19,7 @@ private function __construct(
private Activities $activities,
private UnitSystem $unitSystem,
private ActivityType $activityType,
private DailyTrainingLoad $trainingLoad,
/** @var StatsContext[] */
private array $metricsDisplayOrder,
private SerializableDateTime $now,
Expand All @@ -32,6 +34,7 @@ public static function create(
Activities $activities,
UnitSystem $unitSystem,
ActivityType $activityType,
DailyTrainingLoad $trainingLoad,
array $metricsDisplayOrder,
SerializableDateTime $now,
TranslatorInterface $translator,
Expand All @@ -40,6 +43,7 @@ public static function create(
activities: $activities,
unitSystem: $unitSystem,
activityType: $activityType,
trainingLoad: $trainingLoad,
metricsDisplayOrder: $metricsDisplayOrder,
now: $now,
translator: $translator,
Expand All @@ -61,7 +65,8 @@ public function build(): array

if ([] === array_filter($data[StatsContext::DISTANCE->value])
&& [] === array_filter($data[StatsContext::MOVING_TIME->value])
&& [] === array_filter($data[StatsContext::ELEVATION->value])) {
&& [] === array_filter($data[StatsContext::ELEVATION->value])
&& [] === array_filter($data[StatsContext::LOAD->value])) {
return []; // @codeCoverageIgnore
}

Expand Down Expand Up @@ -108,6 +113,7 @@ public function build(): array
StatsContext::DISTANCE => $this->unitSystem->distanceSymbol(),
StatsContext::MOVING_TIME => 'h',
StatsContext::ELEVATION => $this->unitSystem->elevationSymbol(),
StatsContext::LOAD => '', // No unit symbol needed for Load
};

$series[] = array_merge_recursive(
Expand Down Expand Up @@ -187,19 +193,21 @@ public function build(): array
}

/**
* @return array{distance: float[], movingTime: float[], elevation: int[]}
* @return array{distance: float[], movingTime: float[], elevation: int[], load: int[]}
*/
private function getData(Weeks $weeks): array
{
$distancePerWeek = [];
$timePerWeek = [];
$elevationPerWeek = [];
$loadPerWeek = [];

/** @var Week $week */
foreach ($weeks as $week) {
$distancePerWeek[$week->getId()] = 0;
$timePerWeek[$week->getId()] = 0;
$elevationPerWeek[$week->getId()] = 0;
$loadPerWeek[$week->getId()] = 0;
}

/** @var Activity $activity */
Expand All @@ -216,6 +224,16 @@ private function getData(Weeks $weeks): array
$timePerWeek[$week] += $activity->getMovingTimeInSeconds();
}

/** @var Week $week */
foreach ($weeks as $week) {
$day = $week->getFrom();
$to = $week->getTo();
while ($day <= $to) {
$loadPerWeek[$week->getId()] += $this->trainingLoad->calculate($day);
$day = SerializableDateTime::fromString($day->modify('+1 day')->format('Y-m-d'));
}
}

$distancePerWeek = array_map(
fn (float|int $distance): float => round($distance, $distance < 100 ? $this->activityType->getDistancePrecision() : 0),
$distancePerWeek
Expand All @@ -230,6 +248,7 @@ private function getData(Weeks $weeks): array
StatsContext::DISTANCE->value => array_values($distancePerWeek),
StatsContext::MOVING_TIME->value => array_values($timePerWeek),
StatsContext::ELEVATION->value => array_values($elevationPerWeek),
StatsContext::LOAD->value => array_values($loadPerWeek),
];
}
}
7 changes: 5 additions & 2 deletions src/Domain/Dashboard/Widget/WeeklyStats/WeeklyStatsWidget.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\Domain\Dashboard\Widget\WeeklyStats;

use App\Domain\Activity\ActivityType;
use App\Domain\Activity\DailyTrainingLoad;
use App\Domain\Activity\EnrichedActivities;
use App\Domain\Calendar\Weeks;
use App\Domain\Dashboard\InvalidDashboardLayout;
Expand All @@ -21,6 +22,7 @@
{
public function __construct(
private EnrichedActivities $enrichedActivities,
private DailyTrainingLoad $dailyTrainingLoad,
private UnitSystem $unitSystem,
private Environment $twig,
private TranslatorInterface $translator,
Expand All @@ -41,8 +43,8 @@ public function guardValidConfiguration(WidgetConfiguration $configuration): voi
if (!is_array($configuration->get('metricsDisplayOrder'))) {
throw new InvalidDashboardLayout('Configuration item "metricsDisplayOrder" must be an array.');
}
if (3 !== count($configuration->get('metricsDisplayOrder'))) {
throw new InvalidDashboardLayout('Configuration item "metricsDisplayOrder" must contain all 3 metrics.');
if (4 !== count($configuration->get('metricsDisplayOrder'))) {
throw new InvalidDashboardLayout('Configuration item "metricsDisplayOrder" must contain all 4 metrics.');
}
foreach ($configuration->get('metricsDisplayOrder') as $metricDisplayOrder) {
if (!StatsContext::tryFrom($metricDisplayOrder)) {
Expand Down Expand Up @@ -79,6 +81,7 @@ public function render(SerializableDateTime $now, WidgetConfiguration $configura
activities: $activitiesPerActivityType[$activityType->value],
unitSystem: $this->unitSystem,
activityType: $activityType,
trainingLoad: $this->dailyTrainingLoad,
metricsDisplayOrder: array_map(
StatsContext::from(...),
$metricsDisplayOrder,
Expand Down
4 changes: 2 additions & 2 deletions src/Domain/Dashboard/Widget/YearlyStatsWidget.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public function getDefaultConfiguration(): WidgetConfiguration
{
return WidgetConfiguration::empty()
->add('enableLastXYearsByDefault', 10)
->add('metricsDisplayOrder', array_map(fn (StatsContext $context) => $context->value, StatsContext::defaultSortingOrder()));
->add('metricsDisplayOrder', array_map(fn (StatsContext $context) => $context->value, StatsContext::defaultChartSortingOrder()));
}

public function guardValidConfiguration(WidgetConfiguration $configuration): void
Expand Down Expand Up @@ -86,7 +86,7 @@ public function render(SerializableDateTime $now, WidgetConfiguration $configura
}

$activityType = ActivityType::from($activityType);
foreach (StatsContext::cases() as $yearlyStatsContext) {
foreach (StatsContext::defaultChartSortingOrder() as $yearlyStatsContext) {
if (in_array($yearlyStatsContext, [StatsContext::DISTANCE, StatsContext::ELEVATION]) && !$activityType->supportsDistanceAndElevation()) {
continue;
}
Expand Down
6 changes: 3 additions & 3 deletions tests/Domain/Dashboard/Widget/WeeklyStatsWidgetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ public static function provideInvalidConfig(): iterable
yield 'invalid "metricsDisplayOrder" key' => [$config, 'Configuration item "metricsDisplayOrder" must be an array.'];

$config = WidgetConfiguration::empty()
->add('metricsDisplayOrder', [1, 2, 3, 4]);
yield 'invalid number of items in "metricsDisplayOrder"' => [$config, 'Configuration item "metricsDisplayOrder" must contain all 3 metrics.'];
->add('metricsDisplayOrder', [1, 2, 3, 4, 5]);
yield 'invalid number of items in "metricsDisplayOrder"' => [$config, 'Configuration item "metricsDisplayOrder" must contain all 4 metrics.'];

$config = WidgetConfiguration::empty()
->add('metricsDisplayOrder', ['test', 2, 3]);
->add('metricsDisplayOrder', ['test', 2, 3, 4]);
yield 'invalid value in "metricsDisplayOrder"' => [$config, 'Configuration item "metricsDisplayOrder" contains invalid value "test".'];
}

Expand Down
Loading