Completed
Push — master ( 69bbac...c6a45b )
by Dragos
03:11
created

Track::startDateTime()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 0
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()
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...
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()
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...
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();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->recomputeLength() can also be of type integer. However, the property $length is declared as type double. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
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;
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...
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