Время класса A:
Day 1 => 08:00-09:00 | 11:00-12:00 | 13:00-15:00 | 20:00-21:00
Day 2 => 12:00-13:00 | 14:00-15:00
Day 3 => 08:00-09:00 | 16:00-17:00 | 18:00-19:00
Day 4 => 10:00-11:00 | 12:00-14:00 | 14:00-16:00
Day 5 => 08:00-10:00 | 13:00-15:00
Day 6 => 80:00-09:00 | 10:00-11:00
Время класса B:
Day 1 => 10:00-11:00 | 17:00-19:00
Day 2 => 08:00-09:00 | 11:00-12:00
Day 3 => 08:00-09:00 | 17:00-18:00 | 20:00-21:00
Day 4 => 08:00-09:00 | 14:00-16:00 | 17:00-18:00
Day 5 => 08:00-10:00 | 14:00-15:00
Day 6 => 10:00-11:00
Как проверить два класса времени конфликта
Потому что перекрывающиеся периоды не могут быть простыми ==
Для сравнения, периоды занятий должны быть разбиты на начальный и конечный чанки и обработаны индивидуально. К сожалению, это делает блок кода с большим количеством циклов — но это неизбежно.
array_walk_recursive()
используется для подготовки ваших входных данных. Функция, по замыслу, повторяет только «листовые узлы» $sched
— это означает, что $v
никогда не будет массивом, это всегда будет строка времени. Функция также «неосведомлена по глубине», поэтому единственный способ правильно изменить оригинал $sched
данные должны сделать $v
изменяемый по ссылке (см .: &$v
).
Как только данные реструктурированы, наступает время зацикливаться. Серия из 3 последовательных циклов пересекает «целевые» подмассивы класса и дня для сравнения. Еще 2 цикла используются для доступа к тем же подрешеткам (периодам) Дня всех других Классов. Реализованные ранее сборки кода array_walk_recursive()
еще раз, чтобы уменьшить общее количество циклов, но это не лучшая практика, потому что использование цикла foreach с ранним выходом с break(2)
экономит итерации и повышает эффективность.
Предполагая, что некоторые классы может у меня нет дня с периодом, я выпекла проверку на день, чтобы убедиться, что мой метод не вызывает уведомлений / предупреждений на основе отсутствующих поднаборов Day.
Код: (демонстрация)
$sched=[
'Class A'=>[
'Day 1'=>['10:00-11:00','11:00-12:00','13:00-15:00','20:00-21:00'],
'Day 2'=>['12:00-13:00','14:00-15:00'],
'Day 3'=>['08:00-09:00','16:00-17:00','18:00-19:00'],
'Day 4'=>['10:00-11:00','12:00-14:00','14:00-16:00'],
'Day 5'=>['08:00-10:00','13:00-15:00'],
'Day 6'=>['08:00-09:00','10:00-11:00']
],
'Class B'=>[
'Day 1'=>['09:30-10:30','17:00-19:00'],
'Day 2'=>['08:00-09:00','11:00-12:00'],
'Day 3'=>['08:00-09:00','17:00-18:00','20:00-21:00'],
'Day 4'=>['08:00-09:00','14:00-16:00','17:00-18:00'],
'Day 5'=>['08:00-10:00','14:00-15:00'],
'Day 6'=>['10:00-11:00']
],
'Class C'=>[
'Day 1'=>['12:00-14:00']
]
];
// Preparation: Split the dashed time spans into chunked subarrays containing start and end times
// e.g. $sched['Class A']['Day 1'][['10:00','11:00'],['17:00','19:00']]
array_walk_recursive($sched,function(&$v){$v=explode('-',$v);});
// Comparisons:
foreach($sched as $class=>$days){
$other_classes=array_diff_key($sched,[$class=>'']); // same array without target class
foreach($days as $day=>$spans){
//echo "\n\n$class, $day";
foreach($spans as $period=>$span){
//echo "\nchecking {$span[0]} & {$span[1]}";
foreach($other_classes as $other_class=>$other_days){
if(isset($other_days[$day])){ // this avoids Notices/Warning about non-existent day in class
foreach($other_days[$day] as $other_period=>$other_span){ // compare other classes on same day
//echo "\nversus {$other_span[0]} & {$other_span[1]}";
if(($span[0]>=$other_span[0] && $span[0]<$other_span[1]) || ($span[1]<=$other_span[1] && $span[1]>$other_span[0])){
$result[]="Clash: $class,$day#".++$period.": {$span[0]}-{$span[1]} vs $other_class,$day#".++$other_period.": {$other_span[0]}-{$other_span[1]}";
break(2); // no need to further check this $span for clashes
}
}
}
}
}
}
}
echo implode("\n",$result);
Других решений пока нет …