Skip to content

Commit 059bc83

Browse files
ISSUE-109: Render athlete name in head title
1 parent b5d85a2 commit 059bc83

File tree

39 files changed

+287
-116
lines changed

39 files changed

+287
-116
lines changed

config/services.yaml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,11 @@ services:
6868
factory: [ App\Domain\Strava\StravaRefreshToken, 'fromString' ]
6969
arguments: ['%env(string:STRAVA_REFRESH_TOKEN)%']
7070

71-
athleteBirthDate:
71+
App\Domain\Strava\Athlete\AthleteBirthDate:
7272
class: App\Domain\Strava\Athlete\AthleteBirthDate
7373
factory: [ App\Domain\Strava\Athlete\AthleteBirthDate, 'fromString' ]
7474
arguments: ['%env(string:ATHLETE_BIRTHDAY)%']
7575

76-
App\Domain\Strava\Athlete\Athlete:
77-
class: App\Domain\Strava\Athlete\Athlete
78-
factory: [ App\Domain\Strava\Athlete\Athlete, 'create' ]
79-
arguments: ['@athleteBirthDate']
80-
8176
App\Domain\Strava\Activity\ActivityTypesToImport:
8277
factory: [ 'App\Domain\Strava\Activity\ActivityTypesToImport', from ]
8378
arguments: [ '%env(json:ACTIVITY_TYPES_TO_IMPORT)%' ]

src/Console/ImportStravaDataConsoleCommand.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use App\Domain\Strava\Activity\ImportActivities\ImportActivities;
66
use App\Domain\Strava\Activity\Stream\CalculateBestStreamAverages\CalculateBestStreamAverages;
77
use App\Domain\Strava\Activity\Stream\ImportActivityStreams\ImportActivityStreams;
8+
use App\Domain\Strava\Athlete\ImportAthlete\ImportAthlete;
89
use App\Domain\Strava\Athlete\Weight\ImportAthleteWeight\ImportAthleteWeight;
910
use App\Domain\Strava\Challenge\ImportChallenges\ImportChallenges;
1011
use App\Domain\Strava\Ftp\ImportFtp\ImportFtp;
@@ -43,6 +44,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
4344

4445
$this->migrationRunner->run();
4546

47+
$this->commandBus->dispatch(new ImportAthlete($output));
4648
$this->commandBus->dispatch(new ImportActivities($output));
4749
$this->commandBus->dispatch(new ImportActivityStreams($output));
4850
$this->commandBus->dispatch(new ImportSegments($output));

src/Domain/Nominatim/LiveNominatim.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace App\Domain\Nominatim;
66

77
use App\Infrastructure\Serialization\Json;
8+
use App\Infrastructure\Time\Sleep;
89
use App\Infrastructure\ValueObject\Geography\Coordinate;
910
use GuzzleHttp\Client;
1011
use GuzzleHttp\RequestOptions;
@@ -13,6 +14,7 @@
1314
{
1415
public function __construct(
1516
private Client $client,
17+
private Sleep $sleep,
1618
) {
1719
}
1820

@@ -35,6 +37,8 @@ public function reverseGeocode(Coordinate $coordinate): Location
3537

3638
$response = Json::decode($response->getBody()->getContents());
3739

40+
$this->sleep->sweetDreams(1);
41+
3842
return Location::fromState($response['address']);
3943
}
4044
}

src/Domain/Strava/Activity/ActivityIntensity.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,21 @@
44

55
namespace App\Domain\Strava\Activity;
66

7-
use App\Domain\Strava\Athlete\Athlete;
7+
use App\Domain\Strava\Athlete\AthleteRepository;
88
use App\Domain\Strava\Ftp\FtpRepository;
99
use App\Infrastructure\Exception\EntityNotFound;
1010

1111
final readonly class ActivityIntensity
1212
{
1313
public function __construct(
14-
private Athlete $athlete,
14+
private AthleteRepository $athleteRepository,
1515
private FtpRepository $ftpRepository,
1616
) {
1717
}
1818

1919
public function calculate(Activity $activity): ?int
2020
{
21+
$athlete = $this->athleteRepository->find();
2122
try {
2223
// To calculate intensity, we need
2324
// 1) Max and average heart rate
@@ -34,7 +35,7 @@ public function calculate(Activity $activity): ?int
3435
}
3536

3637
if ($averageHeartRate = $activity->getAverageHeartRate()) {
37-
$athleteMaxHeartRate = $this->athlete->getMaxHeartRate($activity->getStartDate());
38+
$athleteMaxHeartRate = $athlete->getMaxHeartRate($activity->getStartDate());
3839
// Use simplified, less accurate calculation.
3940
// maxHeartRate = = (220 - age) x 0.92
4041
// intensityFactor = averageHeartRate / maxHeartRate

src/Domain/Strava/Activity/ImportActivities/ImportActivitiesCommandHandler.php

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@
1616
use App\Infrastructure\CQRS\Bus\Command;
1717
use App\Infrastructure\CQRS\Bus\CommandHandler;
1818
use App\Infrastructure\Exception\EntityNotFound;
19-
use App\Infrastructure\KeyValue\Key;
20-
use App\Infrastructure\KeyValue\KeyValue;
21-
use App\Infrastructure\KeyValue\KeyValueStore;
22-
use App\Infrastructure\KeyValue\Value;
23-
use App\Infrastructure\Time\Sleep;
2419
use App\Infrastructure\ValueObject\Geography\Coordinate;
2520
use App\Infrastructure\ValueObject\Identifier\UuidFactory;
2621
use App\Infrastructure\ValueObject\Time\SerializableDateTime;
@@ -36,12 +31,10 @@ public function __construct(
3631
private OpenMeteo $openMeteo,
3732
private Nominatim $nominatim,
3833
private ActivityRepository $activityRepository,
39-
private KeyValueStore $keyValueStore,
4034
private FilesystemOperator $filesystem,
4135
private ActivityTypesToImport $activityTypesToImport,
4236
private StravaDataImportStatus $stravaDataImportStatus,
4337
private UuidFactory $uuidFactory,
44-
private Sleep $sleep,
4538
) {
4639
}
4740

@@ -50,13 +43,6 @@ public function handle(Command $command): void
5043
assert($command instanceof ImportActivities);
5144
$command->getOutput()->writeln('Importing activities...');
5245

53-
$athlete = $this->strava->getAthlete();
54-
// Store in KeyValue store, so we don't need to query Strava again.
55-
$this->keyValueStore->save(KeyValue::fromState(
56-
key: Key::ATHLETE_ID,
57-
value: Value::fromString($athlete['id'])
58-
));
59-
6046
$allActivityIds = $this->activityRepository->findActivityIds();
6147
$activityIdsToDelete = array_combine(
6248
$allActivityIds->map(fn (ActivityId $activityId) => (string) $activityId),
@@ -89,7 +75,6 @@ public function handle(Command $command): void
8975
));
9076

9177
$activity->updateLocation($reverseGeocodedAddress);
92-
$this->sleep->sweetDreams(1);
9378
}
9479

9580
$this->activityRepository->update($activity);

src/Domain/Strava/Activity/Stream/StreamBasedActivityHeartRateRepository.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use App\Domain\Strava\Activity\ActivityId;
88
use App\Domain\Strava\Activity\ActivityRepository;
9-
use App\Domain\Strava\Athlete\Athlete;
9+
use App\Domain\Strava\Athlete\AthleteRepository;
1010
use App\Domain\Strava\Athlete\HeartRateZone;
1111

1212
final class StreamBasedActivityHeartRateRepository implements ActivityHeartRateRepository
@@ -17,7 +17,7 @@ final class StreamBasedActivityHeartRateRepository implements ActivityHeartRateR
1717
public function __construct(
1818
private readonly ActivityRepository $activityRepository,
1919
private readonly ActivityStreamRepository $activityStreamRepository,
20-
private readonly Athlete $athlete,
20+
private readonly AthleteRepository $athleteRepository,
2121
) {
2222
}
2323

@@ -61,6 +61,7 @@ private function getCachedHeartRateZones(): array
6161
return StreamBasedActivityHeartRateRepository::$cachedHeartRateZonesPerActivity;
6262
}
6363

64+
$athlete = $this->athleteRepository->find();
6465
$activities = $this->activityRepository->findAll();
6566
$heartRateStreams = $this->activityStreamRepository->findByStreamType(StreamType::HEART_RATE);
6667

@@ -79,7 +80,7 @@ private function getCachedHeartRateZones(): array
7980
continue;
8081
}
8182

82-
$athleteMaxHeartRate = $this->athlete->getMaxHeartRate($activity->getStartDate());
83+
$athleteMaxHeartRate = $athlete->getMaxHeartRate($activity->getStartDate());
8384

8485
/** @var ActivityStream $stream */
8586
$stream = $heartRateStreamsForActivity->getFirst();

src/Domain/Strava/Athlete/Athlete.php

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,36 @@
44

55
namespace App\Domain\Strava\Athlete;
66

7+
use App\Infrastructure\ValueObject\String\Name;
78
use App\Infrastructure\ValueObject\Time\SerializableDateTime;
89

9-
final readonly class Athlete
10+
final readonly class Athlete implements \JsonSerializable
1011
{
1112
private function __construct(
12-
private SerializableDateTime $birthDate,
13+
/** @var array<string, mixed> */
14+
private array $data,
1315
) {
1416
}
1517

16-
public static function create(SerializableDateTime $birthDate): self
18+
/**
19+
* @param array<string, mixed> $data
20+
*/
21+
public static function create(
22+
array $data,
23+
): self {
24+
return new self(
25+
data: $data,
26+
);
27+
}
28+
29+
public function getAthleteId(): string
1730
{
18-
return new self($birthDate);
31+
return (string) $this->data['id'];
1932
}
2033

2134
public function getBirthDate(): SerializableDateTime
2235
{
23-
return $this->birthDate;
36+
return SerializableDateTime::fromString($this->data['birthDate']);
2437
}
2538

2639
public function getAgeInYears(SerializableDateTime $on): int
@@ -32,4 +45,17 @@ public function getMaxHeartRate(SerializableDateTime $on): int
3245
{
3346
return 220 - $this->getAgeInYears($on);
3447
}
48+
49+
public function getName(): Name
50+
{
51+
return Name::fromString(sprintf('%s %s', $this->data['firstname'] ?? 'John', $this->data['lastname'] ?? 'Doe'));
52+
}
53+
54+
/**
55+
* @return array<string, mixed>
56+
*/
57+
public function jsonSerialize(): array
58+
{
59+
return $this->data;
60+
}
3561
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Domain\Strava\Athlete;
6+
7+
interface AthleteRepository
8+
{
9+
public function save(Athlete $athlete): void;
10+
11+
public function find(): Athlete;
12+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Domain\Strava\Athlete\ImportAthlete;
6+
7+
use App\Infrastructure\CQRS\Bus\DomainCommand;
8+
use Symfony\Component\Console\Output\OutputInterface;
9+
10+
final class ImportAthlete extends DomainCommand
11+
{
12+
public function __construct(
13+
private readonly OutputInterface $output,
14+
) {
15+
}
16+
17+
public function getOutput(): OutputInterface
18+
{
19+
return $this->output;
20+
}
21+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Domain\Strava\Athlete\ImportAthlete;
6+
7+
use App\Domain\Strava\Athlete\Athlete;
8+
use App\Domain\Strava\Athlete\AthleteBirthDate;
9+
use App\Domain\Strava\Athlete\AthleteRepository;
10+
use App\Domain\Strava\Strava;
11+
use App\Infrastructure\CQRS\Bus\Command;
12+
use App\Infrastructure\CQRS\Bus\CommandHandler;
13+
14+
final readonly class ImportAthleteCommandHandler implements CommandHandler
15+
{
16+
public function __construct(
17+
private Strava $strava,
18+
private AthleteBirthDate $athleteBirthDate,
19+
private AthleteRepository $athleteRepository,
20+
) {
21+
}
22+
23+
public function handle(Command $command): void
24+
{
25+
assert($command instanceof ImportAthlete);
26+
$command->getOutput()->writeln('Importing athlete...');
27+
28+
$athlete = $this->strava->getAthlete();
29+
$this->athleteRepository->save(Athlete::create([
30+
...$athlete,
31+
'birthDate' => $this->athleteBirthDate,
32+
]));
33+
}
34+
}

0 commit comments

Comments
 (0)