TimeSlotHelper::rightJoinWithout()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
/*
4
 * This file is part of the core-library package.
5
 *
6
 * (c) 2018 WEBEWEB
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace WBW\Library\Core\Utility;
13
14
use WBW\Library\Core\Argument\Helper\DateTimeHelper;
15
use WBW\Library\Core\Sorter\QuickSort;
16
17
/**
18
 * Time slot helper.
19
 *
20
 * @author webeweb <https://github.com/webeweb/>
21
 * @package WBW\Library\Core\Utility
22
 */
23
class TimeSlotHelper {
24
25
    /**
26
     * Determines if a time slot A contains a time slot b.
27
     *
28
     * @param TimeSlot $a The time slot A.
29
     * @param TimeSlot $b The time slot B.
30
     * @return bool Returns true in case of success, false otherwise.
31
     */
32
    public static function contains(TimeSlot $a, TimeSlot $b): bool {
33
        $c1 = DateTimeHelper::isBetween($b->getStartDate(), $a->getStartDate(), $a->getEndDate());
34
        $c2 = DateTimeHelper::isBetween($b->getEndDate(), $a->getStartDate(), $a->getEndDate());
35
        return $c1 && $c2;
36
    }
37
38
    /**
39
     * Determines if two time slots are equals.
40
     *
41
     * @param TimeSlot $a The time slot A.
42
     * @param TimeSlot $b The time slot B.
43
     * @return bool Returns true in case of success, false otherwise.
44
     */
45
    public static function equals(TimeSlot $a, TimeSlot $b): bool {
46
47
        if (false === DateTimeHelper::equals($a->getStartDate(), $b->getStartDate())) {
48
            return false;
49
        }
50
51
        if (false === DateTimeHelper::equals($a->getEndDate(), $b->getEndDate())) {
52
            return false;
53
        }
54
55
        if (count($a->getTimeSlots()) !== count($b->getTimeSlots())) {
56
            return false;
57
        }
58
59
        for ($i = count($a->getTimeSlots()) - 1; 0 <= $i; --$i) {
60
            if (false === static::equals($a->getTimeSlots()[$i], $b->getTimeSlots()[$i])) {
61
                return false;
62
            }
63
        }
64
65
        return true;
66
    }
67
68
    /**
69
     * Full join two time slots.
70
     *
71
     * @param TimeSlot $a The time slot A.
72
     * @param TimeSlot $b The time slot B.
73
     * @return TimeSlot|null Returns a time slot in case of success, null otherwise.
74
     */
75
    public static function fullJoin(TimeSlot $a, TimeSlot $b): ?TimeSlot {
76
77
        if (false === static::hasFullJoin($a, $b)) {
78
            return null;
79
        }
80
81
        $startDate = DateTimeHelper::getSmaller($a->getStartDate(), $b->getStartDate());
82
        $endDate   = DateTimeHelper::getGreater($a->getEndDate(), $b->getEndDate());
83
84
        return new TimeSlot(clone $startDate, clone $endDate);
85
    }
86
87
    /**
88
     * Full join two time slots without time slots intersection.
89
     *
90
     * @param TimeSlot $a The time slot A.
91
     * @param TimeSlot $b The time slot B.
92
     * @return TimeSlot[]|null Returns the time slots in case of success, null otherwise.
93
     */
94
    public static function fullJoinWithout(TimeSlot $a, TimeSlot $b): ?array {
95
96
        $leftJoins  = static::leftJoinWithout($a, $b);
97
        $rightJoins = static::rightJoinWithout($a, $b);
98
99
        if (null === $leftJoins && null === $rightJoins) {
100
            return null;
101
        }
102
        if (null === $leftJoins) {
103
            return $rightJoins;
104
        }
105
        if (null === $rightJoins) {
106
            return $leftJoins;
107
        }
108
109
        return static::sort(array_merge($leftJoins, $rightJoins));
110
    }
111
112
    /**
113
     * Get the duration.
114
     *
115
     * @param TimeSlot[] $timeSlots the time slots.
116
     * @return int Returns the duration.
117
     */
118
    public static function getDuration(array $timeSlots): int {
119
120
        $duration = 0;
121
122
        foreach ($timeSlots as $current) {
123
            $duration += $current->getDuration();
124
        }
125
126
        return $duration;
127
    }
128
129
    /**
130
     * Determines if a time slot A has full join with time slot B.
131
     *
132
     * @param TimeSlot $a The time slot A.
133
     * @param TimeSlot $b The time slot B.
134
     * @return bool Returns true in case of success, false otherwise.
135
     */
136
    public static function hasFullJoin(TimeSlot $a, TimeSlot $b): bool {
137
        return true === static::hasInnerJoin($a, $b);
138
    }
139
140
    /**
141
     * Determines if a time slot A has an inner join with time slot B.
142
     *
143
     * @param TimeSlot $a The time slot A.
144
     * @param TimeSlot $b The time slot B.
145
     * @return bool Returns true in case of success, false otherwise.
146
     */
147
    public static function hasInnerJoin(TimeSlot $a, TimeSlot $b): bool {
148
        $c1 = DateTimeHelper::isBetween($b->getStartDate(), $a->getStartDate(), $a->getEndDate());
149
        $c2 = DateTimeHelper::isBetween($b->getEndDate(), $a->getStartDate(), $a->getEndDate());
150
        $c3 = DateTimeHelper::isBetween($a->getStartDate(), $b->getStartDate(), $b->getEndDate());
151
        $c4 = DateTimeHelper::isBetween($a->getEndDate(), $b->getStartDate(), $b->getEndDate());
152
        return $c1 || $c2 || $c3 || $c4;
153
    }
154
155
    /**
156
     * Inner join two time slots.
157
     *
158
     * @param TimeSlot $a The time slot A.
159
     * @param TimeSlot $b The time slot B.
160
     * @return TimeSlot|null Returns a time slot in case of success, null otherwise.
161
     */
162
    public static function innerJoin(TimeSlot $a, TimeSlot $b): ?TimeSlot {
163
164
        if (false === static::hasInnerJoin($a, $b)) {
165
            return null;
166
        }
167
168
        $startDate = DateTimeHelper::getGreater($a->getStartDate(), $b->getStartDate());
169
        $endDate   = DateTimeHelper::getSmaller($a->getEndDate(), $b->getEndDate());
170
171
        return new TimeSlot(clone $startDate, clone $endDate);
172
    }
173
174
    /**
175
     * Left join two time slots.
176
     *
177
     * @param TimeSlot $a The time slot A.
178
     * @param TimeSlot $b The time slot B.
179
     * @return TimeSlot|null Returns the time slot in case of success, null otherwise.
180
     */
181
    public static function leftJoin(TimeSlot $a, TimeSlot $b): ?TimeSlot {
182
183
        if (false === static::hasInnerJoin($a, $b)) {
184
            return null;
185
        }
186
187
        return new TimeSlot(clone $a->getStartDate(), clone $a->getEndDate());
188
    }
189
190
    /**
191
     * Left join two time slots without time slot B intersection.
192
     *
193
     * @param TimeSlot $a The time slot A.
194
     * @param TimeSlot $b The time slot B.
195
     * @return TimeSlot[]|null Returns the time slots in case of success, null otherwise.
196
     */
197
    public static function leftJoinWithout(TimeSlot $a, TimeSlot $b): ?array {
198
199
        if (false === static::hasInnerJoin($a, $b) || true === static::contains($b, $a)) {
200
            return null;
201
        }
202
203
        if (true === static::contains($a, $b)) {
204
            return static::sort([
205
                new TimeSlot(clone $a->getStartDate(), clone $b->getStartDate()),
206
                new TimeSlot(clone $b->getEndDate(), clone $a->getEndDate()),
207
            ]);
208
        }
209
210
        $startDate = true === DateTimeHelper::isLessThan($a->getStartDate(), $b->getStartDate()) ? $a->getStartDate() : $b->getEndDate();
211
        $endDate   = true === DateTimeHelper::isGreaterThan($a->getEndDate(), $b->getEndDate()) ? $a->getEndDate() : $b->getStartDate();
212
213
        return [
214
            new TimeSlot(clone $startDate, clone $endDate),
215
        ];
216
    }
217
218
    /**
219
     * Merge.
220
     *
221
     * @param TimeSlot[] $timeSlots The time slots.
222
     * @return TimeSlot[] Returns the merged time slots.
223
     */
224
    public static function merge(array $timeSlots): array {
225
226
        $number = count($timeSlots);
227
228
        if (0 === $number) {
229
            return [];
230
        }
231
232
        $buffer = static::sort($timeSlots);
233
234
        $merged = [$buffer[0]];
235
236
        for ($i = 1; $i < $number; ++$i) {
237
238
            $j = count($merged) - 1;
239
240
            $res = static::fullJoin($merged[$j], $buffer[$i]);
241
            if (null === $res) {
242
                $merged[] = $buffer[$i];
243
            } else {
244
                $merged[$j] = $res;
245
            }
246
        }
247
248
        return $merged;
249
    }
250
251
    /**
252
     * Right join two time slots.
253
     *
254
     * @param TimeSlot $a The time slot A.
255
     * @param TimeSlot $b The time slot B.
256
     * @return TimeSlot|null Returns the time slot in case of success, null otherwise.
257
     */
258
    public static function rightJoin(TimeSlot $a, TimeSlot $b): ?TimeSlot {
259
        return static::leftJoin($b, $a);
260
    }
261
262
    /**
263
     * Right join two time slots without time slot B intersection.
264
     *
265
     * @param TimeSlot $a The time slot A.
266
     * @param TimeSlot $b The time slot B.
267
     * @return TimeSlot[]|null Returns the time slots in case of success, null otherwise.
268
     */
269
    public static function rightJoinWithout(TimeSlot $a, TimeSlot $b): ?array {
270
        return static::leftJoinWithout($b, $a);
271
    }
272
273
    /**
274
     * Sort time slots.
275
     *
276
     * @param TimeSlot[] $timeSlots The time slots.
277
     * @return TimeSlot[] Returns the sorted time slots.
278
     */
279
    public static function sort(array $timeSlots): array {
280
281
        $sorter = new QuickSort($timeSlots, new TimeSlotFunctor());
282
        $sorter->sort();
283
284
        return $sorter->getValues();
285
    }
286
}
287