-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathPresentationConflictChecker.php
132 lines (110 loc) · 4.37 KB
/
PresentationConflictChecker.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<?php
namespace App\Actions\Schedule;
use App\Models\Presentation;
use App\Models\Timeslot;
use Carbon\Carbon;
class PresentationConflictChecker
{
/**
* Based on the passed presentation, room and new start estimates if there
* are any conflicts in the scheduling system
* @param $presentation
* @param $room
* @param $start
* @return bool
*/
public function isClearOfConflicts($presentation, $room, $start): bool
{
$previousPresentation = $this->findConflictPresentationBefore($room, $start);
$nextPresentation = $this->findConflictPresentationAfter($room, $start, $presentation);
// Case 0 - Conditional: The presentation needs to be within the boundaries of the day
if (!$this->isWithinBoundariesOfTheDay($presentation, $start)) {
return false;
}
// Case 1: No presentations in the room before this one or after it that cause conflict
if (is_null($previousPresentation)
&& is_null($nextPresentation)) {
return true;
}
// Case 2: Next presentation that causes conflict is
// actually the same presentation trying to be moved later
if (!is_null($nextPresentation)
&& $presentation->id == $nextPresentation->id
&& is_null($previousPresentation)) {
return true;
}
// Case 3: Previous presentation that causes conflict is
// actually the same presentation trying to be moved earlier
if (!is_null($previousPresentation)
&& $presentation->id == $previousPresentation->id
&& is_null($nextPresentation)) {
return true;
}
return false;
}
/**
* Finds the closest starting presentation before the suggested start time
* to check if a conflict occurs
* @param $room
* @param $suggestedStart
* @return mixed|null null if there is no conflict, otherwise the presentation that causes the conflict
*/
public function findConflictPresentationBefore($room, $suggestedStart): mixed
{
$presentationStartTime = Carbon::parse($suggestedStart);
$potentialConflict = $room->presentations()
->where('start', '<', $presentationStartTime)
->orderBy('start', 'desc')
->first();
if (is_null($potentialConflict)) {
return null;
}
$duration = $potentialConflict->duration;
return Carbon::parse($potentialConflict->start)->copy()->addMinutes($duration) <= $presentationStartTime
? null
: $potentialConflict;
}
/**
* Finds the closest starting presentation after the suggested start time
* to check if a conflict occurs
* @param $room
* @param $suggestedStart
* @param $presentation
* @return mixed|null null if there is no conflict, otherwise the presentation that causes the conflict
*/
public function findConflictPresentationAfter($room, $suggestedStart, $presentation): mixed
{
$duration = $presentation->duration;
$presentationStartTime = Carbon::parse($suggestedStart);
$presentationEndTime = $presentationStartTime->copy()->addMinutes($duration);
$potentialConflict = $room->presentations()
->where('start', '>=', $presentationStartTime)
->orderBy('start', 'asc')
->first();
if (is_null($potentialConflict)) {
return null;
}
$duration = $potentialConflict->duration;
return $presentationEndTime <= Carbon::parse($potentialConflict->start)
? null
: $potentialConflict;
}
/**
* Checks if the suggested starting time of a presentation is not before the starting of the
* conference day and before the ending
* @param $presentation
* @param $startTime
* @return bool
*/
public function isWithinBoundariesOfTheDay($presentation, $startTime)
{
$endTime = Carbon::parse($startTime)->copy()->addMinutes($presentation->duration);
$lastTimeslot = Timeslot::all()
->sortByDesc('start')
->first();
$firstTimeslot = Timeslot::all()
->first();
return $endTime->lte(Carbon::parse($lastTimeslot->start)->addMinutes($lastTimeslot->duration))
&& Carbon::parse($startTime)->gte(Carbon::parse($firstTimeslot->start));
}
}