Написать функцию, которая будет считать количество дней после тренировок

kittycat_13

Здравствуйте! Есть задачка: Вы ходите в тренажёрный зал по определённым дням, например вторникам, четвергам, субботам. Известно сегодняшнее число, и сколько тренировок вы хотите посетить, надо найти, сколько пройдёт календарных дней после посещения этого количества тренировок. Например сегодня понедельник 18 апреля 2016 года, вы ходите в зал по вторникам, четвергам и субботам, хотим узнать, сколько дней пройдёт после посещения шести тренировок. В результате должно получиться 13 дней (тренировки 19, 21, 23, 26, 28 и 30 апреля).

Надо написать функцию, которая будет это делать. Сигнатура функции должна выглядеть следующим образом:

function($startDate, $trainingCount, $schedule)

где $startDate- стартовая дата в виде строки, например, '2016-04-18';

$trainingCount - количество запланированных тренировок в виде целого числа;

$schedule - массив с порядковыми номерами дней недели начиная с 1, пн - 1, вт - 2 и т.д.

Вот что имеется на данный момент:

function calculateDays($startDate, $trainingCount, array $schedule){

$start_date = date("d-m-y", $startDate);
$training_count = (int)$trainingCount;


foreach ($schedule as $day) {
switch ($day) {
    case '1':
    $arr[1] = "Mon";
        break;

    case '2':
    $arr[2] = "Tue";
        break;

        case '3':
    $arr[3] = "Wed";
        break;

        case '4':
    $arr[4] = "Thu";
        break;

        case '5':
    $arr[5] = "Fri";
        break;

        case '6':
    $arr[6] = "Sat";
        break;

        case '7':
    $arr[7] = "Sun";
        break;
}
}


}

Не могу разобраться, как мне найти количество дней, которое пройдёт после этих тренировок.

1 ответ

kittycat_13

Самое главное, что нужно сделать — найти количество полных недель и количество тренировок в оставшейся неделе. Всё. Данные у вас есть.

Вычисляется же просто:

количество тренировок всего/количество тренировок в неделю

В итоге получим дробь, где целое число — сколько целых недель пройдет, остаток — сколько тренировок останется сделать в последнюю неделю. Пример:

10 тренировок | 3 раза в неделю | 10 / 3 = 3.1 => 3 полных недели + 1 тренька

Однако стоит учесть, что это только в случае, когда тренировок на текущей неделе, включая сегодняшний день, не предвидится. В ином же случае формула такая:

(количество тренировок всего - количество тренировок на этой неделе)/количество тренировок в неделю

Пример:

10 тренировок | 3 раза в неделю (пн, ср, пт) | сегодня среда 
следовательно
(10 - 2) / 3 = 8 / 3 = 2.1 => 2 полных недели + 1 тренька

Собственно исходя из данных получится общая формула:

(7 - кол-во дней до сегодняшнего дня) + 
(кол-во полных недель * 7) + 
(кол-во дней до последней тренировки в последнюю неделю) // <-- если остаток не равен нулю!!!

Объясняю более наглядно:

Допустим сегодня воскресенье, намечено 10 тренировок в пн, ср. пт.

$daysOfWeek = [1,2,3,4,5,6,7];
$daysOfTraining = [1,3,5];

На этой неделе тренировок уже не будет, значит 10 / 3 = 3.1 => пройдет 3 недели и еще 1 тренировка (сколько дней до неё вычислим позже). Занесем в переменные:

$wholeNumber = 3; // целые недели
$remainder = 1; // остаточные тренировки

По общей формуле получается:

// так как сегодня воскресенье, 7 день недели, значит вычитаем 7
(7 - 7) +
// 3 полные недели по 7 дней в каждой
($wholeNumber * 7) +
// количество дней до последней тренировки
// мы ищем где находится эта последняя тренировка в массиве с днями недели
// + 1 - так как индекс массивов начинается с нуля
(array_search($daysOfTraining[$remainder - 1], $daysOfWeek) + 1)
= 
0 + 21 + 1 
= 
22 дня

Всё... Далее просто применяем функции работы с датами DateTime::add и к нужной дате прибавляем количество получившихся дней:

$dateStart = '2017-04-22';
$date = new DateTime($dateStart);
$date->add(new DateInterval('P22D')); // P22D значит прибавить период 22 дня
$dateEnd = $date->format('Y-m-d');

echo $dateEnd;

Еще что-нибудь посчитаем:

Сегодня среда, намечено 13 тренировок в пн,вт,cр,пт.

$daysOfWeek = [1,2,3,4,5,6,7];
$daysOfTraining = [1,2,3,5];

(13 - 2) / 4 = 2.3

$wholeNumber = 2; // целые недели
$remainder = 3; // остаточные тренировки

// подсчет дней
(7 - 4) +    
($wholeNumber * 7) +    
(array_search($daysOfTraining[$remainder - 1], $daysOfWeek) + 1)
= 
3 + 14 + 3
= 
20 дней

$dateStart = '2017-04-19';
$date = new DateTime($dateStart);
$date->add(new DateInterval('P20D'));
$dateEnd = $date->format('Y-m-d');

Дополнительно: Скорее всего нужно добавлять еще один день - типа последний день включительно. Иначе получится, что он не включается.

А также если будет короткая тренировка (очень частный случай), например всего 2 тренировки и 2 раза в неделю или 3/3, то есть остаток будет равне нулю, то надо будет посчитать чуть по-другому... более проще... Но такое сложно представить, чтоб человек назначил себе 2 тренировки))

licensed under cc by-sa 3.0 with attribution.