1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types = 1); |
4
|
|
|
|
5
|
|
|
namespace SportTrackerConnector\Core\Workout; |
6
|
|
|
|
7
|
|
|
use SportTrackerConnector\Core\Date\DateInterval; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* A track of a workout. |
11
|
|
|
*/ |
12
|
|
|
class Track |
13
|
|
|
{ |
14
|
|
|
/** |
15
|
|
|
* The sport for the workout. |
16
|
|
|
* |
17
|
|
|
* @var string |
18
|
|
|
*/ |
19
|
|
|
protected $sport = SportMapperInterface::OTHER; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* The track points of this track. |
23
|
|
|
* |
24
|
|
|
* @var TrackPoint[] |
25
|
|
|
*/ |
26
|
|
|
protected $trackPoints = array(); |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* The start date and time of the track. |
30
|
|
|
* |
31
|
|
|
* @var \DateTime |
32
|
|
|
*/ |
33
|
|
|
protected $startDateTime; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* The end date and time of the track. |
37
|
|
|
* |
38
|
|
|
* @var \DateTime |
39
|
|
|
*/ |
40
|
|
|
protected $endDateTime; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Get the length of the track in meters. |
44
|
|
|
* |
45
|
|
|
* @var float |
46
|
|
|
*/ |
47
|
|
|
protected $length = 0; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Constructor. |
51
|
|
|
* |
52
|
|
|
* @param TrackPoint[] $trackPoints The track points. |
53
|
|
|
* @param string $sport The sport for this track. |
54
|
|
|
*/ |
55
|
|
|
public function __construct(array $trackPoints = array(), string $sport = SportMapperInterface::OTHER) |
56
|
|
|
{ |
57
|
|
|
$this->setTrackPoints($trackPoints); |
58
|
|
|
$this->setSport($sport); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Set the sport for this workout. |
63
|
|
|
* |
64
|
|
|
* @param string $sport The sport. |
65
|
|
|
*/ |
66
|
|
|
public function setSport(string $sport) |
67
|
|
|
{ |
68
|
|
|
$this->sport = $sport; |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* Get the sport of the workout. |
73
|
|
|
* |
74
|
|
|
* @return string |
75
|
|
|
*/ |
76
|
|
|
public function sport() : string |
77
|
|
|
{ |
78
|
|
|
return $this->sport; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Add a track point. |
83
|
|
|
* |
84
|
|
|
* @param TrackPoint $trackPoint The track point to add. |
85
|
|
|
*/ |
86
|
|
|
public function addTrackPoint(TrackPoint $trackPoint) |
87
|
|
|
{ |
88
|
|
|
$this->trackPoints[] = $trackPoint; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* Set the track points. |
93
|
|
|
* |
94
|
|
|
* @param TrackPoint[] $trackPoints The track points to set. |
95
|
|
|
*/ |
96
|
|
|
public function setTrackPoints(array $trackPoints) |
97
|
|
|
{ |
98
|
|
|
$this->trackPoints = $trackPoints; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* Get the track points. |
103
|
|
|
* |
104
|
|
|
* @return TrackPoint[] |
105
|
|
|
*/ |
106
|
|
|
public function trackPoints() |
107
|
|
|
{ |
108
|
|
|
return $this->trackPoints; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* Get the last track point. |
113
|
|
|
* |
114
|
|
|
* @return TrackPoint |
115
|
|
|
* @throws \OutOfBoundsException If no track points are defined. |
116
|
|
|
*/ |
117
|
|
|
public function lastTrackPoint() : TrackPoint |
118
|
|
|
{ |
119
|
|
|
$lastTrackPoint = end($this->trackPoints); |
120
|
|
|
|
121
|
|
|
if (!$lastTrackPoint instanceof TrackPoint) { |
122
|
|
|
throw new \OutOfBoundsException('No track points points defined.'); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
reset($this->trackPoints); |
126
|
|
|
|
127
|
|
|
return $lastTrackPoint; |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* Get the start date and time of the track. |
132
|
|
|
* |
133
|
|
|
* @return \DateTime |
134
|
|
|
*/ |
135
|
|
|
public function startDateTime() |
136
|
|
|
{ |
137
|
|
|
if ($this->startDateTime === null) { |
138
|
|
|
$this->recomputeStartDateTime(); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
return $this->startDateTime; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Recompute the start date and time of the track. |
146
|
|
|
* |
147
|
|
|
* @return \DateTime |
148
|
|
|
*/ |
149
|
|
View Code Duplication |
public function recomputeStartDateTime() |
|
|
|
|
150
|
|
|
{ |
151
|
|
|
$this->startDateTime = null; |
152
|
|
|
foreach ($this->trackPoints() as $trackPoint) { |
153
|
|
|
if ($this->startDateTime === null || $this->startDateTime > $trackPoint->dateTime()) { |
154
|
|
|
$this->startDateTime = clone $trackPoint->dateTime(); |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
return $this->startDateTime; |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* Get the start date and time of the track. |
163
|
|
|
* |
164
|
|
|
* @return \DateTime |
165
|
|
|
*/ |
166
|
|
|
public function endDateTime() |
167
|
|
|
{ |
168
|
|
|
if ($this->endDateTime === null) { |
169
|
|
|
$this->recomputeEndDateTime(); |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
return $this->endDateTime; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Recompute the start date and time of the track. |
177
|
|
|
* |
178
|
|
|
* @return \DateTime |
179
|
|
|
*/ |
180
|
|
View Code Duplication |
public function recomputeEndDateTime() |
|
|
|
|
181
|
|
|
{ |
182
|
|
|
$this->endDateTime = null; |
183
|
|
|
foreach ($this->trackPoints() as $trackPoint) { |
184
|
|
|
if ($this->startDateTime === null || $this->endDateTime < $trackPoint->dateTime()) { |
185
|
|
|
$this->endDateTime = clone $trackPoint->dateTime(); |
186
|
|
|
} |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
return $this->endDateTime; |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* Get the duration of the track. |
194
|
|
|
* |
195
|
|
|
* @return DateInterval |
196
|
|
|
*/ |
197
|
|
|
public function duration() |
198
|
|
|
{ |
199
|
|
|
$start = $this->startDateTime(); |
200
|
|
|
$end = $this->endDateTime(); |
201
|
|
|
|
202
|
|
|
$dateDifference = $start->diff($end); |
203
|
|
|
|
204
|
|
|
$dateInterval = new DateInterval('PT1S'); |
205
|
|
|
$dateInterval->y = $dateDifference->y; |
206
|
|
|
$dateInterval->m = $dateDifference->m; |
207
|
|
|
$dateInterval->d = $dateDifference->d; |
208
|
|
|
$dateInterval->h = $dateDifference->h; |
209
|
|
|
$dateInterval->i = $dateDifference->i; |
210
|
|
|
$dateInterval->s = $dateDifference->s; |
211
|
|
|
$dateInterval->invert = $dateDifference->invert; |
212
|
|
|
$dateInterval->days = $dateDifference->days; |
213
|
|
|
|
214
|
|
|
return $dateInterval; |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* Set the length of the track in meters. |
219
|
|
|
* |
220
|
|
|
* @param float $length The length of the track in meters. |
221
|
|
|
*/ |
222
|
|
|
public function setLength($length) |
223
|
|
|
{ |
224
|
|
|
$this->length = $length; |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* Get the length of the track in meters. |
229
|
|
|
* |
230
|
|
|
* @return float |
231
|
|
|
*/ |
232
|
|
|
public function length() |
233
|
|
|
{ |
234
|
|
|
if ($this->length === 0) { |
235
|
|
|
$this->length = $this->recomputeLength(); |
|
|
|
|
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
return $this->length; |
239
|
|
|
|
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
/** |
243
|
|
|
* Recompute the length of the track. |
244
|
|
|
* |
245
|
|
|
* @return float |
246
|
|
|
*/ |
247
|
|
|
public function recomputeLength() |
248
|
|
|
{ |
249
|
|
|
$this->length = 0; |
|
|
|
|
250
|
|
|
|
251
|
|
|
$trackPoints = $this->trackPoints(); |
252
|
|
|
$trackPointsCount = count($trackPoints); |
253
|
|
|
if ($trackPointsCount < 2) { |
254
|
|
|
return 0; |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
for ($i = 1; $i < $trackPointsCount; $i++) { |
258
|
|
|
$previousTrack = $trackPoints[$i - 1]; |
259
|
|
|
$currentTrack = $trackPoints[$i]; |
260
|
|
|
|
261
|
|
|
$this->length += $currentTrack->distance($previousTrack); |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
$this->length = round($this->length, 6); |
265
|
|
|
|
266
|
|
|
return $this->length; |
267
|
|
|
} |
268
|
|
|
} |
269
|
|
|
|
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.