Completed
Push — master ( 59b106...2838f8 )
by Peter
03:34
created

IntervalComparator::cover()   C

Complexity

Conditions 7
Paths 16

Size

Total Lines 32
Code Lines 22

Duplication

Lines 22
Ratio 68.75 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 22
loc 32
ccs 0
cts 26
cp 0
rs 6.7272
cc 7
eloc 22
nc 16
nop 1
crap 56
1
<?php
2
3
/**
4
 * GpsLab component.
5
 *
6
 * @author    Peter Gribanov <[email protected]>
7
 * @copyright Copyright (c) 2016, Peter Gribanov
8
 * @license   http://opensource.org/licenses/MIT
9
 */
10
11
namespace GpsLab\Component\Interval;
12
13
/**
14
 * The comparator must be used only in intervals for safe use the data types.
15
 */
16
class IntervalComparator
17
{
18
    /**
19
     * @var ComparableIntervalInterface
20
     */
21
    private $interval;
22
23
    /**
24
     * @param ComparableIntervalInterface $interval
25
     */
26 43
    public function __construct(ComparableIntervalInterface $interval)
27
    {
28 43
        $this->interval = $interval;
29 43
    }
30
31
    /**
32
     * Checks if this Interval is equal to the specified interval.
33
     *
34
     * @param ComparableIntervalInterface $interval
35
     *
36
     * @return bool
37
     */
38
    public function equal(ComparableIntervalInterface $interval)
39
    {
40
        return (
41
            $this->interval->startPoint()->eq($interval->startPoint()) &&
42
            $this->interval->endPoint()->eq($interval->endPoint()) &&
43
            $this->interval->type()->equal($interval->type())
44
        );
45
    }
46
47
    /**
48
     * Does this interval contain the specified point.
49
     *
50
     * @param IntervalPointInterface $point
51
     *
52
     * @return bool
53
     */
54 7
    public function contains(IntervalPointInterface $point)
55
    {
56 7
        if ($this->interval->startPoint()->eq($point)) {
57 2
            return !$this->interval->type()->startExcluded();
58
        }
59
60 5
        if ($this->interval->endPoint()->eq($point)) {
61 2
            return !$this->interval->type()->endExcluded();
62
        }
63
64 3
        return $this->interval->startPoint()->lt($point) && $this->interval->endPoint()->gt($point);
65
    }
66
67
    /**
68
     * Does this interval intersect the specified interval.
69
     *
70
     * @param ComparableIntervalInterface $interval
71
     *
72
     * @return bool
73
     */
74 8
    public function intersects(ComparableIntervalInterface $interval)
75
    {
76 View Code Duplication
        if (
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
77 8
            $this->interval->startPoint()->gt($interval->endPoint()) ||
78 7
            $this->interval->endPoint()->lt($interval->startPoint())
79 8
        ) {
80 2
            return false;
81
        }
82
83 6
        if ($this->interval->startPoint()->eq($interval->endPoint())) {
84 3
            return !$this->interval->type()->startExcluded() && !$interval->type()->endExcluded();
85
        }
86
87 3
        if ($this->interval->endPoint()->eq($interval->startPoint())) {
88 3
            return !$this->interval->type()->endExcluded() && !$interval->type()->startExcluded();
89
        }
90
91
        return true;
92
    }
93
94
    /**
95
     * Gets the intersection between this interval and another interval.
96
     *
97
     * @param ComparableIntervalInterface $interval
98
     *
99
     * @return ComparableIntervalInterface|null
100
     */
101 12
    public function intersection(ComparableIntervalInterface $interval)
102
    {
103
        // intervals is not intersect or impossible create interval from one point
104
        if (
105 12
            $this->interval->startPoint()->gte($interval->endPoint()) ||
106 10
            $this->interval->endPoint()->lte($interval->startPoint())
107 12
        ) {
108
            // ignore closed intervals:
109
            // [a, b] | [b, c] = [b, b]
110 4
            return null;
111
        }
112
113 8
        $type = IntervalType::TYPE_CLOSED;
114
115 8 View Code Duplication
        if ($this->interval->startPoint()->lt($interval->startPoint())) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
116 4
            $start = $interval->startPoint();
117 4
            if ($interval->type()->startExcluded()) {
118 2
                $type |= IntervalType::TYPE_START_EXCLUDED;
119 2
            }
120 4
        } else {
121 4
            $start = $this->interval->startPoint();
122 4
            if ($this->interval->type()->startExcluded()) {
123 2
                $type |= IntervalType::TYPE_START_EXCLUDED;
124 2
            }
125
        }
126
127 8 View Code Duplication
        if ($this->interval->endPoint()->gt($interval->endPoint())) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
128 4
            $end = $interval->endPoint();
129 4
            if ($interval->type()->endExcluded()) {
130 2
                $type |= IntervalType::TYPE_END_EXCLUDED;
131 2
            }
132 4
        } else {
133 4
            $end = $this->interval->endPoint();
134 4
            if ($this->interval->type()->endExcluded()) {
135 2
                $type |= IntervalType::TYPE_END_EXCLUDED;
136 2
            }
137
        }
138
139 8
        return $this->interval
140 8
            ->withStart($start)
141 8
            ->withEnd($end)
142 8
            ->withType(IntervalType::create($type));
143
    }
144
145
    /**
146
     * Gets the covered interval between this Interval and another interval.
147
     *
148
     * @param ComparableIntervalInterface $interval
149
     *
150
     * @return ComparableIntervalInterface
151
     */
152
    public function cover(ComparableIntervalInterface $interval)
153
    {
154
        $type = IntervalType::TYPE_CLOSED;
155 View Code Duplication
        if ($this->interval->startPoint()->lt($interval->startPoint())) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
156
            $start = $this->interval->startPoint();
157
            if ($interval->type()->startExcluded()) {
158
                $type |= IntervalType::TYPE_START_EXCLUDED;
159
            }
160
        } else {
161
            $start = $interval->startPoint();
162
            if ($this->interval->type()->startExcluded()) {
163
                $type |= IntervalType::TYPE_START_EXCLUDED;
164
            }
165
        }
166
167 View Code Duplication
        if ($this->interval->endPoint()->gt($interval->endPoint())) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
168
            $end = $this->interval->endPoint();
169
            if ($interval->type()->endExcluded()) {
170
                $type |= IntervalType::TYPE_END_EXCLUDED;
171
            }
172
        } else {
173
            $end = $interval->endPoint();
174
            if ($this->interval->type()->endExcluded()) {
175
                $type |= IntervalType::TYPE_END_EXCLUDED;
176
            }
177
        }
178
179
        return $this->interval
180
            ->withStart($start)
181
            ->withEnd($end)
182
            ->withType(IntervalType::create($type));
183
    }
184
185
    /**
186
     * Gets the gap between this interval and another interval.
187
     *
188
     * @param ComparableIntervalInterface $interval
189
     *
190
     * @return ComparableIntervalInterface|null
191
     */
192
    public function gap(ComparableIntervalInterface $interval)
193
    {
194 View Code Duplication
        if ($this->interval->startPoint()->gt($interval->endPoint())) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
195
            $type = IntervalType::TYPE_CLOSED;
196
197
            if (!$interval->type()->endExcluded()) { // invert exclude
198
                $type |= IntervalType::TYPE_START_EXCLUDED;
199
            }
200
201
            if (!$this->interval->type()->startExcluded()) { // invert exclude
202
                $type |= IntervalType::TYPE_END_EXCLUDED;
203
            }
204
205
            return $this->interval
206
                ->withStart($interval->endPoint())
207
                ->withEnd($this->interval->startPoint())
208
                ->withType(IntervalType::create($type));
209
        }
210
211 View Code Duplication
        if ($interval->startPoint()->gt($this->interval->endPoint())) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
212
            $type = IntervalType::TYPE_CLOSED;
213
214
            if (!$this->interval->type()->endExcluded()) { // invert exclude
215
                $type |= IntervalType::TYPE_START_EXCLUDED;
216
            }
217
218
            if (!$interval->type()->startExcluded()) { // invert exclude
219
                $type |= IntervalType::TYPE_END_EXCLUDED;
220
            }
221
222
            return $this->interval
223
                ->withStart($this->interval->endPoint())
224
                ->withEnd($interval->startPoint())
225
                ->withType(IntervalType::create($type));
226
        }
227
228
        return null; // no gap
229
    }
230
231
    /**
232
     * Does this interval abut with the interval specified.
233
     *
234
     * @param ComparableIntervalInterface $interval
235
     *
236
     * @return bool
237
     */
238
    public function abuts(ComparableIntervalInterface $interval)
239
    {
240
        return (
241
            $interval->endPoint()->eq($this->interval->startPoint()) ||
242
            $this->interval->endPoint()->eq($interval->startPoint())
243
        );
244
    }
245
246
    /**
247
     * Joins the interval between the adjacent.
248
     *
249
     * @param ComparableIntervalInterface $interval
250
     *
251
     * @return ComparableIntervalInterface|null
252
     */
253
    public function join(ComparableIntervalInterface $interval)
254
    {
255
        if (!$this->abuts($interval)) {
256
            return null;
257
        }
258
259
        return $this->cover($interval);
260
    }
261
262
    /**
263
     * Gets the union between this interval and another interval.
264
     *
265
     * @param ComparableIntervalInterface $interval
266
     *
267
     * @return ComparableIntervalInterface|null
268
     */
269
    public function union(ComparableIntervalInterface $interval)
270
    {
271
        if (!$this->intersects($interval)) {
272
            return null;
273
        }
274
275
        return $this->cover($interval);
276
    }
277
278
    /**
279
     * The point is before the interval.
280
     *
281
     * @param IntervalPointInterface $point
282
     *
283
     * @return bool
284
     */
285
    public function before(IntervalPointInterface $point)
286
    {
287
        if ($this->interval->startPoint()->eq($point)) {
288
            return $this->interval->type()->startExcluded();
289
        }
290
291
        return $this->interval->startPoint()->gt($point);
292
    }
293
294
    /**
295
     * The point is after the interval.
296
     *
297
     * @param IntervalPointInterface $point
298
     *
299
     * @return bool
300
     */
301
    public function after(IntervalPointInterface $point)
302
    {
303
        if ($this->interval->endPoint()->eq($point)) {
304
            return $this->interval->type()->endExcluded();
305
        }
306
307
        return $this->interval->endPoint()->lt($point);
308
    }
309
}
310