I have the following array from my query and would like to check for room schedule clashes.
0 => {#1413 ▼
"room": "49"
"day": "T-Th"
"c_time": "07:00-08:30"
}
1 => {#1414 ▼
"room": "49"
"day": "T"
"c_time": "07:00-08:30"
}
2 => {#1410 ▼
"room": "49"
"day": "T-Th"
"c_time": "07:00-08:30"
}
3 => {#1411 ▼
"room": "49"
"day": "Th"
"c_time": "07:00-08:00"
}
4 => {#1433 ▼
"room": "51"
"day": "M"
"c_time": "10:00-11:30"
}
5 => {#1409 ▼
"room": "49"
"day": "M-W"
"c_time": "11:30-13:00"
}
6 => {#1416 ▼
"room": "51"
"day": "M-W"
"c_time": "1:00-2:30"
}
What I have tried so far can detect conflicts between single/double day schedule with the same time interval and marking them with(bg-red).
Like('49','T-Th','7:00-8:30'),('49','Th','7:00-8:30'),('49','T','7:00-8:30') But I would also like to mark schedules with overlapping time interval.
Controller
foreach($subj->get() as $keyG=>$pG)
{
$pGx=explode("-",$pG->day);;
foreach($pGx as $xKey=>$xx)
{
$classDayTime[]=array('s_id'=>$pG->id,'s_day_time'=>$pGx[$xKey].$pG->c_time.$pG->room);
}
}
$myarr=array_count_values(array_column($classDayTime,'s_day_time'));
Blade
foreach($subj->paginate(20) as $key=>$p)
{
?>
<tr -",$p->day);
foreach($e as $dKey=>$d)
{
$dt=$d.$p->c_time.$p->room;
foreach($myarr as $ky=>$k)
{
if($dt==$ky)
{
if($k != 1)
{
echo "bg-red";
}
else
echo " ";
}
}
}
?>
">
Quite overwhelmed and lost.
**************************************************************************
var_dump($subj)
Illuminate\Support\Collection::__set_state(array( 'items' => array ( 0 => (object) array( 'room' => '49', 'day' => 'T-Th', 'c_time' => '07:00-08:30', ), 1 => (object) array( 'room' => '49', 'day' => 'T', 'c_time' => '07:00-08:30', ), 2 => (object) array( 'room' => '49', 'day' => 'T-Th', 'c_time' => '07:00-08:30', ), 3 => (object) array( 'room' => '49', 'day' => 'Th', 'c_time' => '07:00-08:00', ), 4 => (object) array( 'room' => '51', 'day' => 'M', 'c_time' => '10:00-11:30', ), 5 => (object) array( 'room' => '49', 'day' => 'M-W', 'c_time' => '11:30-01:00', ), 6 => (object) array( 'room' => '51', 'day' => 'M-W', 'c_time' => '1:00-2:30', ), 7 => (object) array( 'room' => '39', 'day' => 'W', 'c_time' => '01:00-02:30', ), 8 => (object) array( 'room' => '51', 'day' => 'T-Th', 'c_time' => '4:00-5:30', ), 9 => (object) array( 'room' => '51', 'day' => 'W', 'c_time' => '01:00-02:30', ), 10 => (object) array( 'room' => '49', 'day' => 'T', 'c_time' => '01:00-02:30', ), ), 'escapeWhenCastingToString' => false, ))
CodePudding user response:
For every row that has
M-W
orT-Th
etc, we separate that out into 2 different days and store it in our$day_map
.For every given time, we split the start and end times and convert each of them into seconds.
Snippet:
<?php
function getIntervalTimestamps($t){
$t = explode("-", $t);
$f = explode(":", $t[0]);
$s = explode(":", $t[1]);
$f = intval($f[0]) * 3600 intval($f[1]) * 60;
$s = intval($s[0]) * 3600 intval($s[1]) * 60;
if($s < $f) $s = 12 * 3600;
return [$f, $s];
}
Now, for every day in our
$day_map
, we sort all the rows by room and their end times in ascending order.Now, if any previously given end time is greater than the next row's start time, we say that there is an overlap. If not, we can simply move ahead with our current row.
Snippet:
<?php
usort($day, function($a, $b){
if($a['room'] != $b['room']) return $a['room'] <=> $b['room'];
if($a['end'] - $b['end'] == 0) return $a['start'] - $b['start'];
return $a['end'] <=> $b['end'];
});
$end = -1;
$room = -1;
$prev_key = false;
$overlapped_timings = false;
foreach($day as $time){
if($end == -1 || $end <= $time['start'] || $room != $time['room']){
if($overlapped_timings) $data['items'][ $prev_key ]->overlapped = true;
$prev_key = $time['idx'];
$end = $time['end'];
$overlapped_timings = false;
$room = $time['room'];
}else{
$overlapped_timings = true;
$data['items'][ $prev_key ]->overlapped = true;
$prev_key = $time['idx'];
$end = max($end, $time['end']);
}
}
if($overlapped_timings) $data['items'][ $prev_key ]->overlapped = true;