Алгоритм вывода не занятых таймслотов с шагом по 30 минут

Sergio022

Новичок
Всем привет, подскажите, пожалуйста, сломал всю голову себе, как решить задачу.

Есть календарь для бронирования, в базе MySQL хранится информация о занятом времени (timestamp поля start и end).

Задача- вывести доступное к бронированию время (таймслоты заданного размера с шагом по 30 минут).

Например: берём день с 7:00 до 19:00, в этом дне занято с 7:30 до 9:00 и с 14:00 до 17:00 и нужно вывести доступное для бронирования время(например 1.5 часа с шагом в 30 минут).

Должно вывестись:
9:00-10:30;
9:30-11:00;
10:00-11:30;
10:30-12:00;
11:00-12:30;
11:30-13:00;
12:00-13:30;
12:30-14:00;
17:00-18:30;
17:30-19:00
 

ksnk

прохожий
Разбей весь день на минимальные интервалы по полчаса и бери 3 соседних незанятых.
 

Sergio022

Новичок
Разбей весь день на минимальные интервалы по полчаса и бери 3 соседних незанятых.
Да вот попробовал, что-то у меня криво пошло, видимо, можете подсказать, где ошибка?

PHP:
<?php
//определяем шаг времени
$timestep = 30;

// Размер свободного слота для поиска
$servicetime = 90;

//определяем занятое время, минуты
$busytime = array(
    480,
    720,
    840,
    870,
    1020
);

// определить сколько слотов занимает процедура
$timeneed = $servicetime / $timestep;
echo ("Услуга занимает: ");
echo ($timeneed);
echo (" слота, или ");
echo ($servicetime);
echo (" минут<br/>");
// определяем рабочее время (часы)
$hourstart = 8;
$hoursend = 20;

// переводим время в минуты
$worktimestart = $hourstart * 60;
$worktimeend = $hoursend * 60;

//определяем свободное время
$freetime = $worktimestart - $timestep;

while ($freetime <= $worktimeend)
{
    $freetime += $timestep;

    //проверка попадания в диапозон занятого времени
    foreach ($busytime as $busyvalue)
    {

        if ($freetime == $busyvalue)
        {
            echo ('Занятое время: ');
            $hours = floor($freetime / 60);
            $minutes = $freetime % 60;

            $freetimeplus = ($freetime + $servicetime);
            $hoursplus = floor($freetimeplus / 60);
            $minutesplus = $freetimeplus % 60;
            printf('%02d:%02d', $hours, $minutes);
            echo (' - ');
            printf('%02d:%02d', $hoursplus, $minutesplus);
            echo ('<br/>');
        }

    }
}
//создаем массив - все рабочее время
$worktimeslots = range($worktimestart, $worktimeend, $timestep);
//print_r($a);


//Удаляем занятое время из массива
$array = $worktimeslots;
foreach ($busytime as $busyvalue)
{
    if (($key = array_search($busyvalue, $array)) !== false)
    {
        unset($array[$key]);
    }
}
print_r($array);
// Определяем доступное время
//циклом смотрим нумерацию массива подряд
echo ('<br/>');

//смотрим порядковые номера массивов идут ли они подряд
$arrkey = array_keys($array);
$arrkeycount = 0;
$slotscountorder = 1;
foreach ($arrkey as $arrkeyvalue)
{
    $arrkeycount++;
    $arrtrack += $arrkeyvalue;
    if ($arrkeyvalue !== $arrkeycount)
    {
        $slotscountorder = 1;
        while ($arrkeyvalue !== $arrkeycount)
        {
            $arrkeycount++;
        }
    }
    else
    {
        $slotscountorder++;
        if ($slotscountorder >= $timeneed)
        {
            if ($arrvalarr >= $worktimestart)
            {
                echo ('<strong>Доступный слот</strong>');
                echo (' => ');
            }
            //Время начала
            $arrvalarr = $array[$arrkeyvalue] - $servicetime;
            $hoursarr = floor($arrvalarr / 60);
            $minutesarr = $arrvalarr % 60;

            //Время завершения
            $arrtimefinish = $array[$arrkeyvalue];
            $hoursfinish = floor($arrtimefinish / 60);
            $minutesfinish = $arrtimefinish % 60;

            if ($arrvalarr >= $worktimestart)
            {
                printf('%02d:%02d', $hoursarr, $minutesarr);
                echo (' - ');
                printf('%02d:%02d', $hoursfinish, $minutesfinish);
            }
            echo ('<br/>');
            // echo($arrval);
            // echo(' => ');
            
        }
      
    }

}
//print_r($arrkey);


//Выводим слоты с нужным количеством слотов подряд, ограничиваясь временем завершения дня
//выводим элементы массива, которые идут подряд

?>
Вот что выводит:
Услуга занимает: 3 слота, или 90 минут
Занятое время: 08:00 - 09:30
Занятое время: 12:00 - 13:30
Занятое время: 14:00 - 15:30
Занятое время: 14:30 - 16:00
Занятое время: 17:00 - 18:30
Array ( [1] => 510 [2] => 540 [3] => 570 [4] => 600 [5] => 630 [6] => 660 [7] => 690 [9] => 750 [10] => 780 [11] => 810 [14] => 900 [15] => 930 [16] => 960 [17] => 990 [19] => 1050 [20] => 1080 [21] => 1110 [22] => 1140 [23] => 1170 [24] => 1200 )

08:00 - 09:30
Доступный слот => 08:30 - 10:00
Доступный слот => 09:00 - 10:30
Доступный слот => 09:30 - 11:00
Доступный слот => 10:00 - 11:30
Доступный слот => 12:00 - 13:30
Доступный слот => 14:30 - 16:00
Доступный слот => 15:00 - 16:30
Доступный слот => 17:00 - 18:30
Доступный слот => 17:30 - 19:00
Доступный слот => 18:00 - 19:30
Доступный слот => 18:30 - 20:00
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Разбей весь день на минимальные интервалы по полчаса и бери 3 соседних незанятых.
тут можно просто в транзакции проверять, что время свободно, и писать в базу время начала и время конца события
 

ksnk

прохожий
Решай задачу по шагам.
Каждый получасовой интервал определяется 1 значением - временем начала.
Напиши функцию isBusy, которая будет определять - является ли этот получасовой интервал занятым.
Пробежись в цикле по всем получасовым интервалам от начала рабочего дня до окончания.
Если интервал свободен - увеличивай счетчик свободных на 1. Если счетчик =3 - выводи интервал (3 последних), и уменьшай счетчик на 1.
Если интервал занят - сбрасывай счетчик на 0.
профит...
тут можно просто в транзакции проверять ...
То есть для решения учебной задачи на логику ты предлагаешь задействовать базу данных? :) А вдруг базы еще не проходили ? )))
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
дело в другом - я умею не только смотреть на экран, но и понимать значение слов - в данном случае, я понимаю условие задачи
в базе MySQL хранится информация о занятом времени (timestamp поля start и end)
как то, что учет времени в базе по меткам начала и конца интервала - это нефункциональное требование,
а твой алгоритм условиям задачи не соответствует

таймслоты с шагом по 30 минут нужны в выводе - это definition of done,
так что, задача сводится к поиску свободных интервалов по базе, и преобразованию найденных из формата timestamp полей start и end в таймслоты при выводе - никакая не учебная, обычная задача в админках, crm, оформлениях заказов
 
Сверху