Home > Enterprise >  Laravel How To Check For Conflict Schedules in An Array
Laravel How To Check For Conflict Schedules in An Array

Time:12-21

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.

**************************************************************************Desired Output

Problem 1


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 or T-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;

Complete Online Demo

  • Related