Задача о прокрастинации и подсчете рабочего времени

Задача о прокрастинации и подсчете рабочего времени

Тирекс
Тирекс Самый зубастый автор
18 января 2024

Задача для тех, кто хочет победить прокрастинацию с помощью статистики и кода.

Изображение записи

Часто на работе хочется отвлечься и поболтать с коллегами или поскроллить ленты в социальных сетях, и иногда на это уходит много времени. Причина в прокрастинации, поэтому важно вовремя выяснить, сколько задач действительно выполняются в рабочее время, а какие привычки «съедают» его. Попробуйте решить задачу, если работаете с кодом.

Главный герой задачи — Саша. Недавно он выпустился из университета и перешел на фултайм в компании, где работал с последнего курса. Задач стало больше, но молодой человек не успел адаптироваться к увеличившейся нагрузке и по привычке отвлекается на социальные сети и чаты. 

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

Теперь Саша хочет взять от информации максимум — определить, сколько максимально, минимально и в среднем прокрастинировал за день и найти медианное значение этого времени.

Условие

Сотрудник зафиксировал данные за каждый день в формате «hh:mm:ss», где «hh», «mm», «ss» — это часы, минуты и секунды прокрастинации. Это положительное или нулевое число, состоящее из двух цифр.

Пример: 02:33:17, 01:26:49, 03:05:43.

Для аналитики нужны четыре значения в исходном формате «hh:mm:ss»:

  • Среднее время прокрастинации за две недели: чтобы вычислить среднее значение, сложите все числа, а затем разделите сумму на общее количество чисел.
  • Минимальное время прокрастинации: самое низкое значение. Посчитайте все данные в секундах и выявите минимальное время.
  • Максимальное время прокрастинации: самое высокое значение. Посчитайте все данные в секундах и выявите максимальное время.
  • Медианное значение: число, отделяющее верхнюю половину выборки данных от нижней. Чтобы определить медиану, расположите все данные в порядке возрастания и определите среднее при нечетном количестве наблюдений (например, медиана {3, 3, 5, 9, 11} равна 5) или среднее двух средних значений при четном числе (медиана {3, 5, 6, 9} равна (5 + 6) ÷ 2 = 5,5).

Пример:

  • Среднее время прокрастинации: 01:35:17
  • Минимальное время прокрастинации: 00:37:49
  • Максимальное время прокрастинации: 2:45:28 
  • Медианное время прокрастинации: 2:23:51

Данные:

1-й день01:12:376-й день03:52:14
2-й день03:13:477-й день04:01:15
3-й день02:28:198-й день02:29:48
4-й день03:35:169-й день01:54:29
5-й день01:59:5610-й день02:37:17

Задача

Ваша задача — вернуть строки, содержащие четыре искомых значения.

Решение

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

Шаг 1. Заполним нашу таблицу. Для этого нужно привести формат данных к одному значению: убрать пробелы в часах, минутах и секундах, заменить разделитель между числами на двоеточие и проставить нули. Пример: 01:12:37.


    const procrastinationChart = {
 '1 день': '01:12:37',
 '6 день': '03:52:14',
 '2 день': '03:13:47',
 '7 день': '04:01:15',
 '3 день': '02:28:19',
 '8 день': '02:29:48',
 '4 день': '03:35:16',
 '9 день': '01:54:29',
 '5 день': '01:59:56',
 '10 день': '02:37:17',
};

Далее извлечем из таблицы все значения количества времени.


    const procrastinationChart = {
 'Day 1': '01:12:37',
};
const procrastinationData = Object.values(procrastinationChart);

Шаг 2. Переведем время в секунды. Для этого сделаем helper-функцию, которая делит строку на составные части, переводит каждую подстроку в число и сохраняет его в соответствующую переменную. Функция возвращает количество секунд.

Пояснение: скобки не влияют на расчет, но помогают улучшить чтение кода.


    function timeToSeconds(time) {
 const [hours, minutes, seconds] = time.split(':').map((value) => parseInt(value));
 return (hours * 60 * 60) + (minutes * 60) + seconds;
}

Шаг 3. Преобразуем наши данные в количество секунд через helper-функцию и отсортируем по возрастанию.


    const procrastinationDataSec = procrastinationData.map(timeToSeconds);
const preparedData = procrastinationDataSec.sort((a, b) => a - b);

Далее пойдем по вопросам задачи. 

Шаг 4. Чтобы найти среднее, складываем все значения в секундах и делим на 10 — количество дней наблюдения.


    let sum = 0;
for (const value of preparedData) {
 sum = sum + value;
}

const averageProcrastinationSec = Math.round(sum / preparedData.length);

Шаг 5. Чтобы найти минимальное и максимальное значения, возьмем первое и последнее число из наших данных, так как они уже отсортированы по возрастанию.


    const minProcrastinationSec = preparedData.at(0);
const maxProcrastinationSec = preparedData.at(-1);

Если бы мы не отсортировали данные, можно было бы воспользоваться поиском через цикл:


    let min = preparedData[0];
let max = preparedData[0];


for (const value of preparedData) {
 if (value < min) {
   min = value;
 }


 if (value > max) {
   max = value;
 }
}

Или использовать функцию из библиотеки:


    let max = Math.max(...preparedData);
let min = Math.min(...preparedData);

Шаг 6. Для поиска медианного значения нужно проверить количество данных на четность и взять центральное значение.


    let medianProcrastinationSec = 0;
if (preparedData.length % 2 === 0) {
 const firstCenterValue = preparedData.at(preparedData.length / 2 - 1);
 const secondCenterValue = preparedData.at(preparedData.length / 2);
 medianProcrastinationSec = Math.round((firstCenterValue + secondCenterValue) / 2);
} else {
 const centerValueIndex = Math.floor(preparedData.length / 2);
 medianProcrastinationSec = preparedData.at(centerValueIndex);
}

Шаг 7. Чтобы вывести результаты в исходном формате, напишем функцию для форматирования чисел и секунд. 

Для начала получим количество часов: разделим количество секунд два раза на 60 и сохраним целую часть. Потом переведем полученные часы обратно в секунды и вычтем их из общего числа секунд — останется сумма минут и секунд. Чтобы получить количество минут, разделим оставшееся число на 60 и выделим целую часть. Переведем обратно и вычтем — останутся только секунды.

Далее с помощью написанной ранее функции применим форматирование и вернем количество времени в исходном формате.


    function formatTimeDigit(value) {
 let prefix = '';


 if (value < 10) {
   prefix = '0';
 }


 return `${prefix}${value}`;
}


function secondsToTime(totalSeconds) {
  const hours = Math.floor(totalSeconds / 60 / 60);


 const restSeconds = totalSeconds - hours * 60 * 60;
 const minutes = Math.floor(restSeconds / 60);
 const seconds = restSeconds - minutes * 60;


 return `${formatTimeDigit(hours)}:${formatTimeDigit(minutes)}:${formatTimeDigit(seconds)}`;
}

Шаг 8. Отформатируем результаты и выведем искомые значения.


    const averageProcrastinationTime = secondsToTime(averageProcrastinationSec);
const minProcrastinationTime = secondsToTime(minProcrastinationSec);
const maxProcrastinationTime = secondsToTime(maxProcrastinationSec);
const medianProcrastinationTime = secondsToTime(medianProcrastinationSec);


console.log(`Среднее время прокрастинации: ${averageProcrastinationTime}`);
console.log(`Минимальное время прокрастинации: ${minProcrastinationTime}`);
console.log(`Максимальное время прокрастинации: ${maxProcrastinationTime}`);
console.log(`Медианное время прокрастинации: ${medianProcrastinationTime}`);

Получившийся результат: в среднем за две недели Саша тратил 02:44:30 рабочего времени на переписки в чатах и другие отвлекающие факторы, минимально — 01:12:37, а максимально — 04:01:15. Медианное значение — 02:33:33.

Полезные материалы

Теперь Саша четко понимает, куда уходит время в офисе, и работает над тем, чтобы избавиться от надоевших вредных привычек. Большая мечта Саши — стать реально крутым специалистом, поэтому он готов приложить все необходимые усилия, чтобы прокачать навыки.

Мы предложили Саше четыре материала из базы Академии Selectel, которые помогут ему быстрее достичь своей цели: