Track::duration()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 14
nc 1
nop 0
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace SportTrackerConnector\Core\Workout;
6
7
use Assert\Assertion;
8
use SportTrackerConnector\Core\Date\DateInterval;
9
10
/**
11
 * A track of a workout.
12
 */
13
final class Track
14
{
15
    /**
16
     * The sport for the workout.
17
     *
18
     * @var string
19
     */
20
    private $sport = SportMapperInterface::OTHER;
21
22
    /**
23
     * The track points of this track.
24
     *
25
     * @var TrackPoint[]
26
     */
27
    private $trackPoints = array();
28
29
    /**
30
     * The start date and time of the track.
31
     *
32
     * @var \DateTimeImmutable
33
     */
34
    private $startDateTime;
35
36
    /**
37
     * The end date and time of the track.
38
     *
39
     * @var \DateTimeImmutable
40
     */
41
    private $endDateTime;
42
43
    /**
44
     * Get the length of the track in meters.
45
     *
46
     * @var float
47
     */
48
    private $length = 0;
49
50
    /**
51
     * Constructor.
52
     *
53
     * @param TrackPoint[] $trackPoints The track points.
54
     * @param string $sport The sport for this track.
55
     */
56
    public function __construct(array $trackPoints = array(), string $sport = SportMapperInterface::OTHER)
57
    {
58
        Assertion::allIsInstanceOf($trackPoints, TrackPoint::class);
59
60
        $this->trackPoints = $trackPoints;
61
        $this->sport = $sport;
62
    }
63
64
    /**
65
     * Get the sport of the workout.
66
     *
67
     * @return string
68
     */
69
    public function sport(): string
70
    {
71
        return $this->sport;
72
    }
73
74
    /**
75
     * Get the track points.
76
     *
77
     * @return TrackPoint[]
78
     */
79
    public function trackPoints()
80
    {
81
        return $this->trackPoints;
82
    }
83
84
    /**
85
     * Get the last track point.
86
     *
87
     * @return TrackPoint
88
     * @throws \OutOfBoundsException If no track points are defined.
89
     */
90
    public function lastTrackPoint(): TrackPoint
91
    {
92
        $lastTrackPoint = end($this->trackPoints);
93
94
        if (!$lastTrackPoint instanceof TrackPoint) {
95
            throw new \OutOfBoundsException('No track points points defined.');
96
        }
97
98
        reset($this->trackPoints);
99
100
        return $lastTrackPoint;
101
    }
102
103
    /**
104
     * Get the start date and time of the track.
105
     *
106
     * @return \DateTimeImmutable
107
     */
108
    public function startDateTime(): \DateTimeImmutable
109
    {
110
        if ($this->startDateTime === null) {
111
            $this->recomputeStartDateTime();
112
        }
113
114
        return $this->startDateTime;
115
    }
116
117
    /**
118
     * Recompute the start date and time of the track.
119
     *
120
     * @return \DateTimeImmutable
121
     */
122 View Code Duplication
    private function recomputeStartDateTime(): \DateTimeImmutable
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
123
    {
124
        $this->startDateTime = null;
125
        foreach ($this->trackPoints() as $trackPoint) {
126
            if ($this->startDateTime === null || $this->startDateTime > $trackPoint->dateTime()) {
127
                $this->startDateTime = clone $trackPoint->dateTime();
128
            }
129
        }
130
131
        return $this->startDateTime;
132
    }
133
134
    /**
135
     * Get the start date and time of the track.
136
     *
137
     * @return \DateTimeImmutable
138
     */
139
    public function endDateTime(): \DateTimeImmutable
140
    {
141
        if ($this->endDateTime === null) {
142
            $this->recomputeEndDateTime();
143
        }
144
145
        return $this->endDateTime;
146
    }
147
148
    /**
149
     * Recompute the start date and time of the track.
150
     *
151
     * @return \DateTimeImmutable
152
     */
153 View Code Duplication
    private function recomputeEndDateTime(): \DateTimeImmutable
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
154
    {
155
        $this->endDateTime = null;
156
        foreach ($this->trackPoints() as $trackPoint) {
157
            if ($this->startDateTime === null || $this->endDateTime < $trackPoint->dateTime()) {
158
                $this->endDateTime = clone $trackPoint->dateTime();
159
            }
160
        }
161
162
        return $this->endDateTime;
163
    }
164
165
    /**
166
     * Get the duration of the track.
167
     *
168
     * @return DateInterval
169
     */
170
    public function duration()
171
    {
172
        $start = $this->startDateTime();
173
        $end = $this->endDateTime();
174
175
        $dateDifference = $start->diff($end);
176
177
        $dateInterval = new DateInterval('PT1S');
178
        $dateInterval->y = $dateDifference->y;
179
        $dateInterval->m = $dateDifference->m;
180
        $dateInterval->d = $dateDifference->d;
181
        $dateInterval->h = $dateDifference->h;
182
        $dateInterval->i = $dateDifference->i;
183
        $dateInterval->s = $dateDifference->s;
184
        $dateInterval->invert = $dateDifference->invert;
185
        $dateInterval->days = $dateDifference->days;
186
187
        return $dateInterval;
188
    }
189
190
    /**
191
     * Set the length of the track in meters.
192
     *
193
     * @param float $length The length of the track in meters.
194
     * @deprecated
195
     */
196
    public function setLength(float $length)
197
    {
198
        $this->length = $length;
199
    }
200
201
    /**
202
     * Get the length of the track in meters.
203
     *
204
     * @return float
205
     */
206
    public function length(): float
207
    {
208
        if ($this->length === 0) {
209
            $this->length = $this->recomputeLength();
210
        }
211
212
        return $this->length;
213
214
    }
215
216
    /**
217
     * Recompute the length of the track.
218
     *
219
     * @return float
220
     */
221
    private function recomputeLength(): float
222
    {
223
        $this->length = 0;
0 ignored issues
show
Documentation Bug introduced by
The property $length was declared of type double, but 0 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
224
225
        $trackPoints = $this->trackPoints();
226
        $trackPointsCount = count($trackPoints);
227
        if ($trackPointsCount < 2) {
228
            return 0;
229
        }
230
231
        for ($i = 1; $i < $trackPointsCount; $i++) {
232
            $previousTrack = $trackPoints[$i - 1];
233
            $currentTrack = $trackPoints[$i];
234
235
            $this->length += $currentTrack->distanceFromPoint($previousTrack);
236
        }
237
238
        $this->length = round($this->length, 6);
239
240
        return $this->length;
241
    }
242
}
243