Skip to content
Open
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
6bc7bb0
Выполнены задания, доступные тесты пройдены
SemyonMakhaev Oct 24, 2016
7db0021
Исправлен tryLater
SemyonMakhaev Oct 24, 2016
cc5a2e6
Исправлен tryLater снова
SemyonMakhaev Oct 24, 2016
0584d0c
При форматировании нахожу время, если прежде оно не было найдено
SemyonMakhaev Oct 25, 2016
788af54
Исправлена ошибка добавления элементов в коллекцию во время работы fo…
SemyonMakhaev Oct 25, 2016
2ef1e2c
Сдвигаю все интервалы при вызове tryLater
SemyonMakhaev Oct 25, 2016
f1d58f0
Могу совершить ограбление за 0 минут в нулевой интервал
SemyonMakhaev Oct 25, 2016
e417fa2
Время задачи ограничено ПН 00:00 и СР 23:59
SemyonMakhaev Oct 25, 2016
7b59a58
Добавлены все дни недели
SemyonMakhaev Oct 25, 2016
309025a
Добавлена проверка открытия и закрытия банка
SemyonMakhaev Oct 25, 2016
bda4842
Откатились
SemyonMakhaev Oct 25, 2016
69ce06d
Принимаю расписание любого количества бандитов
SemyonMakhaev Oct 26, 2016
4501f46
Сдвинута нижняя граница на 1 минуту
SemyonMakhaev Oct 26, 2016
5470d03
no star
SemyonMakhaev Oct 26, 2016
3bfabcb
Исправлена функция format
SemyonMakhaev Oct 26, 2016
320ead4
Исправлен tryLater
SemyonMakhaev Oct 26, 2016
89dba6b
Исправлены коварные табы
SemyonMakhaev Oct 26, 2016
b89c5c5
Исправлен tryLater для случая, если время не найдено
SemyonMakhaev Oct 26, 2016
2ae96cc
Скорректирована правая граница времени
SemyonMakhaev Oct 26, 2016
4efad33
no star
SemyonMakhaev Oct 26, 2016
b5f57a5
star
SemyonMakhaev Oct 26, 2016
4415ace
Убрал поддержку нулевых интервалов
SemyonMakhaev Oct 26, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
233 changes: 231 additions & 2 deletions robbery.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,59 @@ exports.isStar = true;
* @returns {Object}
*/
exports.getAppropriateMoment = function (schedule, duration, workingHours) {
console.info(schedule, duration, workingHours);
var timeZone = parseInt(workingHours.from.split('+')[1]);
var convertedSchedule = convertIntervals(
getCommonSchedule(schedule), timeZone);
var convertedWorkingHours = convertIntervals(
getIntervals(workingHours), timeZone);

return {
possibleIntervals: getPossibleIntervals(
convertedWorkingHours, convertedSchedule),
duration: duration,
robberyTime: undefined,

/**
* Находит время, не раньше переданного
* @param {Date} lower - Нижняя граница времени
* @param {Date} upper - Верхняя граница времени
* @returns {Date} Подходящее время
*/
findWithin: function (lower, upper) {
var appropriateTimes = [];
var robberyDuration = this.duration;
this.possibleIntervals.forEach(function (interval) {
if (lower > interval.from) {
interval.from = lower;
}
if (upper < interval.to) {
interval.to = upper;
}
if (interval.to > interval.from &&
new Date(interval.to - interval.from) >=
new Date(1000 * 60 * robberyDuration)) {
appropriateTimes.push(interval.from);
}
});
appropriateTimes.sort();

return appropriateTimes[0];
},

/**
* Найдено ли время
* @returns {Boolean}
*/
exists: function () {
var appropriateTime = this.findWithin(
new Date(2016, 9, 24, 5),
new Date(2016, 9, 26, 28, 59, 59));
if (typeof appropriateTime !== 'undefined') {
this.robberyTime = appropriateTime;

return true;
}

return false;
},

Expand All @@ -35,7 +79,8 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) {
* @returns {String}
*/
format: function (template) {
return template;
return typeof this.robberyTime === 'undefined' &&
!this.exists() ? '' : formatTime(this.robberyTime, template);
},

/**
Expand All @@ -44,7 +89,191 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) {
* @returns {Boolean}
*/
tryLater: function () {
if (typeof this.robberyTime === 'undefined') {
this.exists();
}
if (typeof this.robberyTime === 'undefined' ||
this.robberyTime < new Date(2016, 9, 24, 5) ||
this.robberyTime > new Date(2016, 9, 26, 28, 59, 59)) {
return false;
}
var border = new Date(Number(this.robberyTime) +
Number(new Date(1000 * 60 * 30)));
var newTime = this.findWithin(border,
new Date(2016, 9, 26, 28, 59, 59));
if (typeof newTime !== 'undefined') {
this.robberyTime = newTime;

return true;
}

return false;
}
};
};

/**
* Удаляет пересечение доступных интервалов с недоступными
* @param {Object} available - Доступные временные интервалы
* @param {Object} unavailable - Недоступные временные интервалы
* @returns {Object} Подходящие временные интервалы
*/
function getPossibleIntervals(available, unavailable) {
var intervalsToCheck = removeIntersection(available, unavailable);
var intervals = [];
intervalsToCheck.forEach(function (interval) {
if (interval.from <= interval.to) {
intervals.push(interval);
}
});

return intervals;
}

/**
* @param {Object} available - Доступные временные интервалы
* @param {Object} unavailable - Недоступные временные интервалы
* @returns {Object} Набор подходящих интервалов
*/
function removeIntersection(available, unavailable) {
var intervalsToCheck = [];
while (available.length > 0) {
var possible = available.pop();
var newInterval = checkIntersection(possible, unavailable);
if (typeof newInterval !== 'undefined') {
available.push(newInterval);
}
intervalsToCheck.push(possible);
}

return intervalsToCheck;
}

/**
* @param {Object} possible - Доступный временной интервал
* @param {Object} unavailable - Набор недоступных интервалов
* @returns {Object} - Новый интервал, образованный при разрыве предыдущего
*/
function checkIntersection(possible, unavailable) {
var newInterval;
unavailable.forEach(function (impossible) {
if (possible.from <= impossible.from &&
impossible.from <= possible.to &&
possible.to <= impossible.to) {
possible.to = impossible.from;
}
if (impossible.from <= possible.from &&
possible.from <= impossible.to &&
impossible.to <= possible.to) {
possible.from = impossible.to;
}
if (impossible.from <= possible.from &&
possible.from <= possible.to &&
possible.to <= impossible.to) {
possible.from = possible.to;
}
if (possible.from <= impossible.from &&
impossible.to <= possible.to) {
var tempPossibleTo = possible.to;
possible.to = impossible.from;
newInterval = {
from: impossible.to,
to: tempPossibleTo
};
}
});

return newInterval;
}

/**
* @param {Object} workHours - Часы работы
* @returns {Object} Временные интервалы в пределах задачи (ПН 00:00 - СР 23:59)
*/
function getIntervals(workHours) {
var intervals = [];
['ПН ', 'ВТ ', 'СР '].forEach(function (day) {
intervals.push({
from: day + workHours.from,
to: day + workHours.to
});
});

return intervals;
}

/**
* @param {Object} gangSchedule - Расписание Банды
* @returns {Object} Общее расписание (список из интервалов)
*/
function getCommonSchedule(gangSchedule) {
var intervals = [];
for (var gangster in gangSchedule) {
if (typeof gangster !== 'undefined') {
gangSchedule[gangster].forEach(function (interval) {
intervals.push({
from: interval.from,
to: interval.to
});
});
}
}

return intervals;
}

var DAYS = ['ВС', 'ПН', 'ВТ', 'СР'];

/**
* @param {Date} time - Время для форматирования
* @param {String} template - Шаблон
* @returns {String}
*/
function formatTime(time, template) {
var components = [
time.getHours().toString(),
time.getMinutes().toString()
];
components.forEach(function (component, idx, arr) {
if (component.length === 1) {
arr[idx] = '0' + component;
}
});
if (components[0] === '24') {
components[0] = '00';
}

return template.replace('%HH', components[0])
.replace('%MM', components[1])
.replace('%DD', DAYS[time.getDay()]);
}

/**
* @param {Object} intervals - Временные интервалы в строках
* @param {Number} timeZone - Часовой пояс банка
* @returns {Object} Временные интервалы в Date
*/
function convertIntervals(intervals, timeZone) {
intervals.forEach(function (interval) {
interval.from = convertTime(interval.from, timeZone);
interval.to = convertTime(interval.to, timeZone);
});

return intervals;
}

var DAY_TO_DATE = { 'ВС': 23, 'ПН': 24, 'ВТ': 25, 'СР': 26,
'ЧТ': 27, 'ПТ': 28, 'СББ': 29 };

/**
* @param {String} time - Строковое время
* @param {Number} timeZone - Часовой пояс банка
* @returns {Date} Время в формате Date
*/
function convertTime(time, timeZone) {
var dateParts = time.split(/[ :+]/);
var hour = parseInt(dateParts[1]) + timeZone - parseInt(dateParts[3]);
var minutes = parseInt(dateParts[2]);

return new Date(2016, 9, DAY_TO_DATE[dateParts[0]], hour, minutes);
}