From d9a4a164983b8d1935f06c0921d13123e07dec19 Mon Sep 17 00:00:00 2001 From: Ilya Nizovcev Date: Tue, 30 Oct 2018 00:42:26 +0500 Subject: [PATCH] =?UTF-8?q?=D0=BE=D1=82=D0=B2=D1=80=D0=B0=D1=82=D0=B8?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D0=B5=20=D0=B7=D0=B0=D0=B4?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B5,=20=D0=B8=D0=B7=D0=B2=D0=B8=D0=BD?= =?UTF-8?q?=D0=B8=D1=82=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + robbery.js | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 137 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 919a523..4ca8466 100755 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "main": "robbery.js", + "private": true, "scripts": { "lint": "eslint .", "test": "npm run lint && mocha *.spec.js --exit" diff --git a/robbery.js b/robbery.js index ed84b5d..2197b88 100755 --- a/robbery.js +++ b/robbery.js @@ -6,6 +6,88 @@ */ const isStar = true; +const MINUTES_IN_HOUR = 60; +const MINUTES_IN_DAY = 24 * MINUTES_IN_HOUR; +const DAYS = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС']; + +let bankTimeZone = 0; +let startWorkBank = 0; +let endWorkBank = 0; +let freeTimeIntervalsFrom = []; +let freeTimeIntervalsTo = []; +let rightTimeStart = []; +let rightTimeEnd = []; +let timeNumber = 0; + +function splitTime(time) { + const parsingTime = time.split(/ |:|\+/); + const day = DAYS.indexOf(parsingTime[0]); + const timeInMinutes = parsingTime[1] * MINUTES_IN_HOUR + + Number(parsingTime[2]) + Number(day * MINUTES_IN_DAY) + + Number(MINUTES_IN_HOUR * (bankTimeZone - parsingTime[3])); + + return timeInMinutes; +} + +function bankTimeInMinutes(workingHours) { + const workingHoursFrom = workingHours.from.split(/:|\+/); + const workingHoursTo = workingHours.to.split(/:|\+/); + + bankTimeZone = workingHoursFrom[2]; + startWorkBank = workingHoursFrom[0] * MINUTES_IN_HOUR + Number(workingHoursFrom[1]); + endWorkBank = workingHoursTo[0] * MINUTES_IN_HOUR + Number(workingHoursTo[1]); +} + +function sortTime(firstTime, secondTime) { + return firstTime - secondTime; +} + +function checkInterval(duration) { + for (let i = 0; i < freeTimeIntervalsFrom.length; i++) { + if (freeTimeIntervalsTo[i] - freeTimeIntervalsFrom[i] >= duration) { + rightTimeStart.push(freeTimeIntervalsFrom[i]); + rightTimeEnd.push(freeTimeIntervalsTo[i]); + } + } + + rightTimeStart.sort(sortTime); + rightTimeEnd.sort(sortTime); +} + +function confluence(robberyTimeFrom, robberyTimeTo, i) { + if (robberyTimeTo >= freeTimeIntervalsTo[i] || robberyTimeTo <= freeTimeIntervalsFrom[i]) { + freeTimeIntervalsFrom[i] = freeTimeIntervalsFrom[i]; + } else if (robberyTimeTo >= freeTimeIntervalsTo[i] && + robberyTimeFrom > freeTimeIntervalsFrom[i]) { + freeTimeIntervalsTo[i] = robberyTimeFrom; + } else if (robberyTimeTo < freeTimeIntervalsTo[i] && robberyTimeFrom <= freeTimeIntervalsFrom[i]) { + freeTimeIntervalsFrom[i] = robberyTimeTo; + } else if (robberyTimeTo < freeTimeIntervalsTo[i] && robberyTimeFrom > freeTimeIntervalsFrom[i]) { + freeTimeIntervalsTo.push(freeTimeIntervalsTo[i]); + freeTimeIntervalsFrom.push(robberyTimeTo); + freeTimeIntervalsTo[i] = robberyTimeFrom; + } else { + freeTimeIntervalsFrom[i] = 0; + freeTimeIntervalsTo[i] = 0; + } +} + +function interval(robberyTimeFrom, robberyTimeTo) { + for (let i = 0; i < freeTimeIntervalsFrom.length; i++) { + confluence(robberyTimeFrom, robberyTimeTo, i); + } +} + +function exclude(schedule) { + for (let robbery of Object.keys(schedule)) { + schedule[robbery].forEach(item => { + const robberyTimeFrom = splitTime(item.from); + const robberyTimeTo = splitTime(item.to); + interval(robberyTimeFrom, robberyTimeTo); + }); + } +} + /** * @param {Object} schedule – Расписание Банды * @param {Number} duration - Время на ограбление в минутах @@ -17,6 +99,22 @@ const isStar = true; function getAppropriateMoment(schedule, duration, workingHours) { console.info(schedule, duration, workingHours); + freeTimeIntervalsFrom = []; + freeTimeIntervalsTo = []; + rightTimeStart = []; + rightTimeEnd = []; + timeNumber = 0; + + bankTimeInMinutes(workingHours); + + for (let i = 0; i < 3; i++) { + freeTimeIntervalsFrom.push(startWorkBank + MINUTES_IN_DAY * i); + freeTimeIntervalsTo.push(endWorkBank + MINUTES_IN_DAY * i); + } + + exclude(schedule); + checkInterval(duration); + return { /** @@ -24,6 +122,10 @@ function getAppropriateMoment(schedule, duration, workingHours) { * @returns {Boolean} */ exists: function () { + if (rightTimeStart.length) { + return true; + } + return false; }, @@ -34,7 +136,28 @@ function getAppropriateMoment(schedule, duration, workingHours) { * @returns {String} */ format: function (template) { - return template; + if (!this.exists()) { + return ''; + } + + const time = rightTimeStart[timeNumber]; + const day = 0; + + while (time >= MINUTES_IN_DAY) { + time -= MINUTES_IN_DAY; + day++; + } + + let minutes = time % MINUTES_IN_DAY; + let hours = (time - minutes) / MINUTES_IN_HOUR; + + minutes = (minutes < 10 ? '0' : '') + minutes; + hours = (hours < 10 ? '0' : '') + hours; + + return template + .replace('%HH', hours) + .replace('%MM', minutes) + .replace('%DD', DAYS[day]); }, /** @@ -43,6 +166,18 @@ function getAppropriateMoment(schedule, duration, workingHours) { * @returns {Boolean} */ tryLater: function () { + const time = rightTimeEnd[timeNumber] - rightTimeStart[timeNumber]; + + if (time - 30 >= duration) { + rightTimeStart[timeNumber] += 30; + + return true; + } else if (rightTimeStart[timeNumber + 1]) { + timeNumber++ + + return true; + } + return false; } }; @@ -50,6 +185,5 @@ function getAppropriateMoment(schedule, duration, workingHours) { module.exports = { getAppropriateMoment, - isStar };