Completed
Push — master ( 8b40f4...1a4202 )
by Peter
13:15
created

IntervalComparator::equal()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
c 0
b 0
f 0
rs 9.4285
cc 3
eloc 5
nc 3
nop 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
    public function __construct(ComparableIntervalInterface $interval)
27
    {
28
        $this->interval = $interval;
29
    }
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
    public function contains(IntervalPointInterface $point)
51
    {
52
        if ($this->interval->startPoint()->eq($point)) {
53
            return !$this->interval->type()->startExcluded();
54
        }
55
56
        if ($this->interval->endPoint()->eq($point)) {
57
            return !$this->interval->type()->endExcluded();
58
        }
59
60
        return $this->interval->startPoint()->lt($point) && $this->interval->endPoint()->gt($point);
61
    }
62
63
    /**
64
     * @param ComparableIntervalInterface $interval
65
     * @param bool $check_interval_type
66
     *
67
     * @return bool
68
     */
69
    public function intersects(ComparableIntervalInterface $interval, $check_interval_type = true)
70
    {
71
        if (
72
            $this->interval->startPoint()->gt($interval->endPoint()) ||
73
            $this->interval->endPoint()->lt($interval->startPoint())
74
        ) {
75
            return false;
76
        }
77
78
        if ($check_interval_type) {
79
            if ($this->interval->startPoint()->eq($interval->endPoint())) {
80
                return !$this->interval->type()->startExcluded() && !$interval->type()->endExcluded();
81
            }
82
83
            if ($this->interval->endPoint()->eq($interval->startPoint())) {
84
                return !$this->interval->type()->endExcluded() && !$interval->type()->startExcluded();
85
            }
86
        }
87
88
        return true;
89
    }
90
91
    /**
92
     * @param ComparableIntervalInterface $interval
93
     *
94
     * @return ComparableIntervalInterface|null
95
     */
96
    public function intersection(ComparableIntervalInterface $interval)
97
    {
98
        // intervals is not intersect or impossible create interval from one point
99
        if (
100
            $this->interval->startPoint()->gte($interval->endPoint()) ||
101
            $this->interval->endPoint()->lte($interval->startPoint())
102
        ) {
103
            // ignore closed intervals:
104
            // [a, b] | [b, c] = [b, b]
105
            return null;
106
        }
107
108
        $type = IntervalType::TYPE_CLOSED;
109
110
        if ($this->interval->startPoint()->lt($interval->startPoint())) {
111
            $start = $interval->startPoint();
112
            if ($interval->type()->startExcluded()) {
113
                $type |= IntervalType::TYPE_START_EXCLUDED;
114
            }
115
        } else {
116
            $start = $this->interval->startPoint();
117
            if ($this->interval->type()->startExcluded()) {
118
                $type |= IntervalType::TYPE_START_EXCLUDED;
119
            }
120
        }
121
122
        if ($this->interval->endPoint()->gt($interval->endPoint())) {
123
            $end = $interval->endPoint();
124
            if ($interval->type()->endExcluded()) {
125
                $type |= IntervalType::TYPE_END_EXCLUDED;
126
            }
127
        } else {
128
            $end = $this->interval->endPoint();
129
            if ($this->interval->type()->endExcluded()) {
130
                $type |= IntervalType::TYPE_END_EXCLUDED;
131
            }
132
        }
133
134
        return $this->interval
135
            ->withStart($start)
136
            ->withEnd($end)
137
            ->withType(IntervalType::create($type));
138
    }
139
140
    /**
141
     * The point is before the interval.
142
     *
143
     * @param IntervalPointInterface $point
144
     *
145
     * @return bool
146
     */
147
    public function before(IntervalPointInterface $point)
148
    {
149
        return $this->interval->startPoint()->gt($point);
150
    }
151
152
    /**
153
     * The point is after the interval.
154
     *
155
     * @param IntervalPointInterface $point
156
     *
157
     * @return bool
158
     */
159
    public function after(IntervalPointInterface $point)
160
    {
161
        return $this->interval->endPoint()->lt($point);
162
    }
163
}
164