Completed
Push — master ( c777ad...d0e678 )
by WEBEWEB
01:18
created

TimeSlotHelper   A

Complexity

Total Complexity 39

Size/Duplication

Total Lines 291
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 39
lcom 1
cbo 4
dl 0
loc 291
rs 9.28
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A contains() 0 5 2
B equals() 0 27 6
A fullJoin() 0 14 2
A fullJoinWithout() 0 20 5
A getDuration() 0 7 2
A hasFullJoin() 0 3 1
A hasInnerJoin() 0 7 4
A innerJoin() 0 14 2
A leftJoin() 0 10 2
B leftJoinWithout() 0 24 6
A merge() 0 34 4
A rightJoin() 0 3 1
A rightJoinWithout() 0 3 1
A sort() 0 9 1
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\Sorting\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) {
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) {
46
47
        // Compare the start dates.
48
        if (false === DateTimeHelper::equals($a->getStartDate(), $b->getStartDate())) {
49
            return false;
50
        }
51
52
        // Compare the end dates.
53
        if (false === DateTimeHelper::equals($a->getEndDate(), $b->getEndDate())) {
54
            return false;
55
        }
56
57
        // Compare the time slots count.
58
        if (count($a->getTimeSlots()) !== count($b->getTimeSlots())) {
59
            return false;
60
        }
61
62
        // Handle each time slot.
63
        for ($i = count($a->getTimeSlots()) - 1; 0 <= $i; --$i) {
64
            if (false === static::equals($a->getTimeSlots()[$i], $b->getTimeSlots()[$i])) {
65
                return false;
66
            }
67
        }
68
69
        //
70
        return true;
71
    }
72
73
    /**
74
     * Full join two time slots.
75
     *
76
     * @param TimeSlot $a The time slot A.
77
     * @param TimeSlot $b The time slot B.
78
     * @return TimeSlot|null Returns a time slot in case of success, null otherwise.
79
     */
80
    public static function fullJoin(TimeSlot $a, TimeSlot $b) {
81
82
        // Has full join ?
83
        if (false === static::hasFullJoin($a, $b)) {
84
            return null;
85
        }
86
87
        // Initialize the date/times.
88
        $startDate = DateTimeHelper::getSmaller($a->getStartDate(), $b->getStartDate());
89
        $endDate   = DateTimeHelper::getGreater($a->getEndDate(), $b->getEndDate());
90
91
        // Return the time slot.
92
        return new TimeSlot(clone $startDate, clone $endDate);
93
    }
94
95
    /**
96
     * Full join two time slots without time slots intersection.
97
     *
98
     * @param TimeSlot $a The time slot A.
99
     * @param TimeSlot $b The time slot B.
100
     * @return TimeSlot[]|null Returns the time slots in case of success, null otherwise.
101
     */
102
    public static function fullJoinWithout(TimeSlot $a, TimeSlot $b) {
103
104
        // Initialize the time slots.
105
        $leftJoins  = static::leftJoinWithout($a, $b);
106
        $rightJoins = static::rightJoinWithout($a, $b);
107
108
        // Check the time slots.
109
        if (null === $leftJoins && null === $rightJoins) {
110
            return null;
111
        }
112
        if (null === $leftJoins) {
113
            return $rightJoins;
114
        }
115
        if (null === $rightJoins) {
116
            return $leftJoins;
117
        }
118
119
        // Return the time slots.
120
        return static::sort(array_merge($leftJoins, $rightJoins));
121
    }
122
123
    /**
124
     * Get the duration.
125
     *
126
     * @param TimeSlot[] $timeSlots the time slots.
127
     * @return int Returns the duration.
128
     */
129
    public static function getDuration(array $timeSlots) {
130
        $output = 0;
131
        foreach ($timeSlots as $current) {
132
            $output += $current->getDuration();
133
        }
134
        return $output;
135
    }
136
137
    /**
138
     * Determines if a time slot A has full join with time slot B.
139
     *
140
     * @param TimeSlot $a The time slot A.
141
     * @param TimeSlot $b The time slot B.
142
     * @return bool Returns true in case of success, false otherwise.
143
     */
144
    public static function hasFullJoin(TimeSlot $a, TimeSlot $b) {
145
        return true === static::hasInnerJoin($a, $b);
146
    }
147
148
    /**
149
     * Determines if a time slot A has an inner join with time slot B.
150
     *
151
     * @param TimeSlot $a The time slot A.
152
     * @param TimeSlot $b The time slot B.
153
     * @return bool Returns true in case of success, false otherwise.
154
     */
155
    public static function hasInnerJoin(TimeSlot $a, TimeSlot $b) {
156
        $c1 = DateTimeHelper::isBetween($b->getStartDate(), $a->getStartDate(), $a->getEndDate());
157
        $c2 = DateTimeHelper::isBetween($b->getEndDate(), $a->getStartDate(), $a->getEndDate());
158
        $c3 = DateTimeHelper::isBetween($a->getStartDate(), $b->getStartDate(), $b->getEndDate());
159
        $c4 = DateTimeHelper::isBetween($a->getEndDate(), $b->getStartDate(), $b->getEndDate());
160
        return $c1 || $c2 || $c3 || $c4;
161
    }
162
163
    /**
164
     * Inner join two time slots.
165
     *
166
     * @param TimeSlot $a The time slot A.
167
     * @param TimeSlot $b The time slot B.
168
     * @return TimeSlot|null Returns a time slot in case of success, null otherwise.
169
     */
170
    public static function innerJoin(TimeSlot $a, TimeSlot $b) {
171
172
        // Has inner join ?
173
        if (false === static::hasInnerJoin($a, $b)) {
174
            return null;
175
        }
176
177
        // Initialize the date/times.
178
        $startDate = DateTimeHelper::getGreater($a->getStartDate(), $b->getStartDate());
179
        $endDate   = DateTimeHelper::getSmaller($a->getEndDate(), $b->getEndDate());
180
181
        // Return the time slot.
182
        return new TimeSlot(clone $startDate, clone $endDate);
183
    }
184
185
    /**
186
     * Left join two time slots.
187
     *
188
     * @param TimeSlot $a The time slot A.
189
     * @param TimeSlot $b The time slot B.
190
     * @return TimeSlot|null Returns the time slot in case of success, null otherwise.
191
     */
192
    public static function leftJoin(TimeSlot $a, TimeSlot $b) {
193
194
        // Has inner join ?
195
        if (false === static::hasInnerJoin($a, $b)) {
196
            return null;
197
        }
198
199
        // Return the time slot.
200
        return new TimeSlot(clone $a->getStartDate(), clone $a->getEndDate());
201
    }
202
203
    /**
204
     * Left join two time slots without time slot B intersection.
205
     *
206
     * @param TimeSlot $a The time slot A.
207
     * @param TimeSlot $b The time slot B.
208
     * @return TimeSlot[]|null Returns the time slots in case of success, null otherwise.
209
     */
210
    public static function leftJoinWithout(TimeSlot $a, TimeSlot $b) {
211
212
        // Has inner join ?
213
        if (false === static::hasInnerJoin($a, $b) || true === static::contains($b, $a)) {
214
            return null;
215
        }
216
217
        // Contains ?
218
        if (true === static::contains($a, $b)) {
219
            return static::sort([
220
                new TimeSlot(clone $a->getStartDate(), clone $b->getStartDate()),
221
                new TimeSlot(clone $b->getEndDate(), clone $a->getEndDate()),
222
            ]);
223
        }
224
225
        // Initialize the date/times.
226
        $startDate = true === DateTimeHelper::isLessThan($a->getStartDate(), $b->getStartDate()) ? $a->getStartDate() : $b->getEndDate();
227
        $endDate   = true === DateTimeHelper::isGreaterThan($a->getEndDate(), $b->getEndDate()) ? $a->getEndDate() : $b->getStartDate();
228
229
        // Return the time slots.
230
        return [
231
            new TimeSlot(clone $startDate, clone $endDate),
232
        ];
233
    }
234
235
    /**
236
     * Merge.
237
     *
238
     * @param TimeSlot[] $timeSlots The time slots.
239
     * @return TimeSlot[] Returns the merged time slots.
240
     */
241
    public static function merge(array $timeSlots) {
242
243
        // Count the time slots.
244
        $number = count($timeSlots);
245
246
        // Check the time slots count.
247
        if (0 === $number) {
248
            return [];
249
        }
250
251
        // Sort the time slots.
252
        $buffer = static::sort($timeSlots);
253
254
        // Initialize the output.
255
        $output = [$buffer[0]];
256
257
        // Handle each time slot.
258
        for ($i = 1; $i < $number; ++$i) {
259
260
            //
261
            $j = count($output) - 1;
262
263
            // Full join the time slots.
264
            $res = static::fullJoin($output[$j], $buffer[$i]);
265
            if (null === $res) {
266
                $output[] = $buffer[$i];
267
            } else {
268
                $output[$j] = $res;
269
            }
270
        }
271
272
        // Return the output.
273
        return $output;
274
    }
275
276
    /**
277
     * Right join two time slots.
278
     *
279
     * @param TimeSlot $a The time slot A.
280
     * @param TimeSlot $b The time slot B.
281
     * @return TimeSlot|null Returns the time slot in case of success, null otherwise.
282
     */
283
    public static function rightJoin(TimeSlot $a, TimeSlot $b) {
284
        return static::leftJoin($b, $a);
285
    }
286
287
    /**
288
     * Right join two time slots without time slot B intersection.
289
     *
290
     * @param TimeSlot $a The time slot A.
291
     * @param TimeSlot $b The time slot B.
292
     * @return TimeSlot[]|null Returns the time slots in case of success, null otherwise.
293
     */
294
    public static function rightJoinWithout(TimeSlot $a, TimeSlot $b) {
295
        return static::leftJoinWithout($b, $a);
296
    }
297
298
    /**
299
     * Sort time slots.
300
     *
301
     * @param TimeSlot[] $timeSlots The time slots.
302
     * @return TimeSlot[] Returns the sorted time slots.
303
     */
304
    public static function sort(array $timeSlots) {
305
306
        // Initialize a Qucik sort.
307
        $sorter = new QuickSort($timeSlots, new TimeSlotFunctor());
308
        $sorter->sort();
309
310
        // Return the time slots.
311
        return $sorter->getValues();
312
    }
313
}
314