-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathPresentationAllocationHelper.php
127 lines (107 loc) · 4.63 KB
/
PresentationAllocationHelper.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
<?php
namespace App\Actions\Schedule;
use App\Models\Timeslot;
use Carbon\Carbon;
class PresentationAllocationHelper
{
/**
* Determines whether the allocation helper can help in scheduling
* @param $presentation
* @param $timeslot
* @param $room
* @return int 0 - cannot help; 1 - can allocate in given timeslot;
* 2 - can allocate in timeslot previous to the give one
*/
public function canHelp($presentation, $timeslot, $room)
{
if ($this->tryToSchedulePresentationInTimeslot($presentation, $timeslot, $room)) {
return 1;
} elseif ($this->tryToScheduleInPreviousTimeslot($presentation, $timeslot, $room)) {
return 2;
}
return 0;
}
/**
* Calculates if it is possible to set the presentation in the wanted timeslot
* and the possible starting
* @param $presentation
* @param $timeslot
* @param $room
* @return Carbon|null returns the possible starting time or null if it is impossible
*/
public function tryToSchedulePresentationInTimeslot($presentation, $timeslot, $room): ?Carbon
{
$conflictChecker = new PresentationConflictChecker();
$previousPresentation = $conflictChecker->findConflictPresentationBefore($room, $timeslot->start);
// This means something is going wrong, if the conflict is not because of starting time,
// it's because of ending one
if (is_null($previousPresentation)) {
return null;
}
$proposedStartingTime = Carbon::parse($previousPresentation->start)
->copy()->addMinutes($previousPresentation->duration);
$timeslotEndingTime = Carbon::parse($timeslot->start)
->copy()->addMinutes(30);
// Means that it cannot be scheduled at all within the wanted timeslot
if ($proposedStartingTime->gte($timeslotEndingTime)) {
return null;
}
$nextPresentation = $conflictChecker
->findConflictPresentationAfter($room, $proposedStartingTime, $presentation);
$conflictChecker = new PresentationConflictChecker();
if (!$conflictChecker->isWithinBoundariesOfTheDay($presentation, $proposedStartingTime)) {
return null;
}
return is_null($nextPresentation) || $nextPresentation->id == $presentation->id
? $proposedStartingTime
: null;
}
/**
* If the timeslot in which the user is trying to allocate, the presentation is too busy
* try to allocate in previous timeslot in a way to still cover the free part of the desired timeslot
* @param $presentation
* @param $timeslot
* @param $room
* @return Carbon|null
*/
public function tryToScheduleInPreviousTimeslot($presentation, $timeslot, $room): ?Carbon
{
$proposedStartingTime = Carbon::parse($timeslot->start)
->copy()->subMinutes($presentation->duration);
$proposedTimeslot = $this->findTimeslotByStartingTime($proposedStartingTime);
$conflictChecker = new PresentationConflictChecker();
$nextPresentation = $conflictChecker
->findConflictPresentationAfter($room, $proposedStartingTime, $presentation);
// If there is a presentation after the suggested time calculation that causes a conflict,
// nothing can be done as of now
if (!is_null($nextPresentation)) {
return null;
}
$conflictChecker = new PresentationConflictChecker();
$previousPresentation = $conflictChecker
->findConflictPresentationBefore($room, $proposedStartingTime->copy()->format('H:i'));
if (!$conflictChecker->isWithinBoundariesOfTheDay($presentation, $proposedStartingTime)) {
return null;
}
return is_null($previousPresentation) || $previousPresentation->id == $presentation->id
? $proposedStartingTime
: null;
}
/**
* Based on the starting time, determine in which timeslot does the time fall
* @param $startingTime
* @return Timeslot|mixed|null returns the timeslot it finds or null if such does not exist
*/
public function findTimeslotByStartingTime($startingTime)
{
$timeslots = Timeslot::all();
$startingTime = Carbon::parse($startingTime);
foreach ($timeslots as $timeslot) {
$timeslotEndTime = Carbon::parse($timeslot->start)->copy()->addMinutes($timeslot->duration);
if ($startingTime->gte(Carbon::parse($timeslot->start)) && $startingTime->lt($timeslotEndTime)) {
return $timeslot;
}
}
return null;
}
}