Completed
Push — master ( ef97c3...705b1d )
by Peter
21:19 queued 05:11
created

IntervalComparator   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 145
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 82.76%

Importance

Changes 0
Metric Value
wmc 26
c 0
b 0
f 0
lcom 1
cbo 3
dl 0
loc 145
ccs 48
cts 58
cp 0.8276
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A equal() 0 8 3
A contains() 0 12 4
B intersects() 0 19 7
D intersection() 0 43 9
A before() 0 4 1
A after() 0 4 1
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
     * @param ComparableIntervalInterface $interval
33
     *
34
     * @return bool
35
     */
36
    public function equal(ComparableIntervalInterface $interval)
37
    {
38
        return (
39
            $this->interval->startPoint()->eq($interval->startPoint()) &&
40
            $this->interval->endPoint()->eq($interval->endPoint()) &&
41
            $this->interval->type()->equal($interval->type())
42
        );
43
    }
44
45
    /**
46
     * @param IntervalPointInterface $point
47
     *
48
     * @return bool
49
     */
50 7
    public function contains(IntervalPointInterface $point)
51
    {
52 7
        if ($this->interval->startPoint()->eq($point)) {
53 2
            return !$this->interval->type()->startExcluded();
54
        }
55
56 5
        if ($this->interval->endPoint()->eq($point)) {
57 2
            return !$this->interval->type()->endExcluded();
58
        }
59
60 3
        return $this->interval->startPoint()->lt($point) && $this->interval->endPoint()->gt($point);
61
    }
62
63
    /**
64
     * @param ComparableIntervalInterface $interval
65
     *
66
     * @return bool
67
     */
68 8
    public function intersects(ComparableIntervalInterface $interval)
69
    {
70
        if (
71 8
            $this->interval->startPoint()->gt($interval->endPoint()) ||
72 7
            $this->interval->endPoint()->lt($interval->startPoint())
73 8
        ) {
74 2
            return false;
75
        }
76
77 6
        if ($this->interval->startPoint()->eq($interval->endPoint())) {
78 3
            return !$this->interval->type()->startExcluded() && !$interval->type()->endExcluded();
79
        }
80
81 3
        if ($this->interval->endPoint()->eq($interval->startPoint())) {
82 3
            return !$this->interval->type()->endExcluded() && !$interval->type()->startExcluded();
83
        }
84
85
        return true;
86
    }
87
88
    /**
89
     * @param ComparableIntervalInterface $interval
90
     *
91
     * @return ComparableIntervalInterface|null
92
     */
93 12
    public function intersection(ComparableIntervalInterface $interval)
94
    {
95
        // intervals is not intersect or impossible create interval from one point
96
        if (
97 12
            $this->interval->startPoint()->gte($interval->endPoint()) ||
98 10
            $this->interval->endPoint()->lte($interval->startPoint())
99 12
        ) {
100
            // ignore closed intervals:
101
            // [a, b] | [b, c] = [b, b]
102 4
            return null;
103
        }
104
105 8
        $type = IntervalType::TYPE_CLOSED;
106
107 8
        if ($this->interval->startPoint()->lt($interval->startPoint())) {
108 4
            $start = $interval->startPoint();
109 4
            if ($interval->type()->startExcluded()) {
110 2
                $type |= IntervalType::TYPE_START_EXCLUDED;
111 2
            }
112 4
        } else {
113 4
            $start = $this->interval->startPoint();
114 4
            if ($this->interval->type()->startExcluded()) {
115 2
                $type |= IntervalType::TYPE_START_EXCLUDED;
116 2
            }
117
        }
118
119 8
        if ($this->interval->endPoint()->gt($interval->endPoint())) {
120 4
            $end = $interval->endPoint();
121 4
            if ($interval->type()->endExcluded()) {
122 2
                $type |= IntervalType::TYPE_END_EXCLUDED;
123 2
            }
124 4
        } else {
125 4
            $end = $this->interval->endPoint();
126 4
            if ($this->interval->type()->endExcluded()) {
127 2
                $type |= IntervalType::TYPE_END_EXCLUDED;
128 2
            }
129
        }
130
131 8
        return $this->interval
132 8
            ->withStart($start)
133 8
            ->withEnd($end)
134 8
            ->withType(IntervalType::create($type));
135
    }
136
137
    /**
138
     * The point is before the interval.
139
     *
140
     * @param IntervalPointInterface $point
141
     *
142
     * @return bool
143
     */
144
    public function before(IntervalPointInterface $point)
145
    {
146
        return $this->interval->startPoint()->gt($point);
147
    }
148
149
    /**
150
     * The point is after the interval.
151
     *
152
     * @param IntervalPointInterface $point
153
     *
154
     * @return bool
155
     */
156
    public function after(IntervalPointInterface $point)
157
    {
158
        return $this->interval->endPoint()->lt($point);
159
    }
160
}
161