From f7778925878ad271c274cd631fcc7cf832bc748c Mon Sep 17 00:00:00 2001 From: Medvedev Denis Date: Thu, 19 Oct 2017 08:02:30 +0500 Subject: [PATCH 1/5] First solution --- package-lock.json | 16 ++-- robbery.js | 210 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 186 insertions(+), 40 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2b4e704..6087ec1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1029,6 +1029,14 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -1038,14 +1046,6 @@ "strip-ansi": "4.0.0" } }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", diff --git a/robbery.js b/robbery.js index 4a8309d..5e4c2dd 100644 --- a/robbery.js +++ b/robbery.js @@ -1,50 +1,196 @@ 'use strict'; -/** - * Сделано задание на звездочку - * Реализовано оба метода и tryLater - */ exports.isStar = true; -/** - * @param {Object} schedule – Расписание Банды - * @param {Number} duration - Время на ограбление в минутах - * @param {Object} workingHours – Время работы банка - * @param {String} workingHours.from – Время открытия, например, "10:00+5" - * @param {String} workingHours.to – Время закрытия, например, "18:00+5" - * @returns {Object} - */ exports.getAppropriateMoment = function (schedule, duration, workingHours) { - console.info(schedule, duration, workingHours); + let profit = []; + let frends = {}; + let lastInterval = {}; + let isTryLater = false; + Object.keys(schedule).forEach(key => { + + let startFree = 0; + frends[key] = []; + schedule[key].forEach(el => { + frends[key].push({ + from: startFree, + to: timeConverter(el.from), + name: key + }); + startFree = timeConverter(el.to); + }); + + frends[key].push({ + from: startFree, + to: 4320, + name: key + }); + + return frends; + }); + + let bankIntervals = mathIntervalsBank(workingHours); + + for (let i = 0; i < bankIntervals.length; i++) { // Перебираем банковские дни + let frendsInterval = { + Danny: [], + Rusty: [], + Linus: [] + }; + + Object.keys(frends).forEach(frend => { + frends[frend].forEach(interval => { + let bankFrom = bankIntervals[i].from; + let bankTo = bankIntervals[i].to; + if ((Math.min(bankFrom, bankTo) < Math.max(interval.from, interval.to)) && + ((Math.min(interval.from, interval.to) < + Math.max(bankFrom, bankTo)))) { + frendsInterval[interval.name].push({ + from: Math.max(bankFrom, interval.from), + to: Math.min(bankTo, interval.to), + name: interval.name + }); + } + + }); + + }); + + let maxFrom; + let minTo; + frendsInterval.Danny.forEach(iD => { + + maxFrom = Math.max(maxFrom, iD.from); + minTo = Math.min(minTo, iD.to); + + frendsInterval.Rusty.forEach(iR => { + + maxFrom = Math.max(iD.from, iR.from); + minTo = Math.min(iD.to, iR.to); + + frendsInterval.Linus.forEach(iL => { + maxFrom = Math.max(maxFrom, iL.from); + minTo = Math.min(minTo, iL.to); + + if ((maxFrom < minTo) && (minTo - maxFrom) >= duration) { + + profit.push({ + from: maxFrom + 300, + to: minTo + 300, + day: i + 1 + }); + } + + }); + + }); + }); + } return { + exists() { + if (profit.length > 0) { + + return true; + } - /** - * Найдено ли время - * @returns {Boolean} - */ - exists: function () { return false; }, + format(template) { + let resObj; + if (profit.length === 0 && !isTryLater) { + return ''; + } else if (profit.length > 0) { + resObj = intervalToString(profit[0].from); + } else { + resObj = intervalToString(lastInterval.from); + } + + return template.replace('%DD', resObj.DD).replace('%HH', resObj.HH) + .replace('%MM', resObj.MM); - /** - * Возвращает отформатированную строку с часами для ограбления - * Например, - * "Начинаем в %HH:%MM (%DD)" -> "Начинаем в 14:59 (СР)" - * @param {String} template - * @returns {String} - */ - format: function (template) { - return template; }, - /** - * Попробовать найти часы для ограбления позже [*] - * @star - * @returns {Boolean} - */ tryLater: function () { + isTryLater = true; + if (profit.length > 0) { + return calcNextMoment(profit[0]); + + } + return false; } }; + + function calcNextMoment() { + lastInterval = JSON.parse(JSON.stringify(profit[0])); + profit[0].from = profit[0].from + 30; + if (profit[0].to - profit[0].from < duration) { + profit.splice(0, 1); + } + if (profit.length > 0) { + + return true; + } + + return false; + } }; + +function timeConverter(T) { + const DAYS = { + 'ПН': 0, + 'ВТ': 1440, + 'СР': 2880 + }; + let timeArr = T.replace(/[+:]/ig, ' ').split(' '); + + return Number(DAYS[timeArr[0]]) + Number(timeArr[1]) * 60 - +Number(timeArr[3]) * 60 + Number(timeArr[2]); +} + +function mathIntervalsBank(obj) { + return [{ + from: timeConverter('ПН ' + obj.from), + to: timeConverter('ПН ' + obj.to) + }, { + from: timeConverter('ВТ ' + obj.from), + to: timeConverter('ВТ ' + obj.to) + }, { + from: timeConverter('СР ' + obj.from), + to: timeConverter('СР ' + obj.to) + } + ]; +} + +function intervalToString(go) { + let resObj = {}; + let mins; + let time = String(go / 1440).split('.')[0]; + + if (time === '0') { + resObj.DD = 'ПН'; + mins = go; + } else if (time === '1') { + resObj.DD = 'ВТ'; + mins = go - 1440; + } else if (time === '2') { + resObj.DD = 'СР'; + mins = go - 2880; + } + + let hoursArr = (mins / 60).toFixed(1).split('.'); + resObj.HH = twoSign(hoursArr[0]); + resObj.MM = twoSign(hoursArr[1] * 6); + + return resObj; +} + +function twoSign(num) { + if (num > 9) { + return num; + } + + return '0' + num; + +} From 0f023555534f7dfc9e2df960f890c32eb1b8476b Mon Sep 17 00:00:00 2001 From: Medvedev Denis Date: Thu, 19 Oct 2017 08:08:04 +0500 Subject: [PATCH 2/5] isStar = false --- robbery.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/robbery.js b/robbery.js index 5e4c2dd..9747894 100644 --- a/robbery.js +++ b/robbery.js @@ -1,6 +1,6 @@ 'use strict'; -exports.isStar = true; +exports.isStar = false; exports.getAppropriateMoment = function (schedule, duration, workingHours) { let profit = []; From 37f639385c1b0544183f3a3ad3bf7961ff2401c0 Mon Sep 17 00:00:00 2001 From: Medvedev Denis Date: Sun, 22 Oct 2017 21:42:40 +0500 Subject: [PATCH 3/5] Fixed --- robbery.js | 203 +++++++++++++++++++++-------------------------------- 1 file changed, 79 insertions(+), 124 deletions(-) diff --git a/robbery.js b/robbery.js index 9747894..029debb 100644 --- a/robbery.js +++ b/robbery.js @@ -1,151 +1,97 @@ 'use strict'; -exports.isStar = false; - +exports.isStar = true; +const DAYS_WEEK = { + 'ПН': 0, + 'ВТ': 1440, + 'СР': 2880 +}; exports.getAppropriateMoment = function (schedule, duration, workingHours) { - let profit = []; - let frends = {}; - let lastInterval = {}; - let isTryLater = false; - Object.keys(schedule).forEach(key => { - - let startFree = 0; - frends[key] = []; - schedule[key].forEach(el => { - frends[key].push({ - from: startFree, - to: timeConverter(el.from), - name: key - }); - startFree = timeConverter(el.to); - }); - - frends[key].push({ - from: startFree, - to: 4320, - name: key - }); - - return frends; - }); - + let timeLine = returnInterval([], [{ + from: 0, + to: 4320 + }], 0); + let friends = getFriendsIntervals(); let bankIntervals = mathIntervalsBank(workingHours); - for (let i = 0; i < bankIntervals.length; i++) { // Перебираем банковские дни - let frendsInterval = { - Danny: [], - Rusty: [], - Linus: [] - }; - - Object.keys(frends).forEach(frend => { - frends[frend].forEach(interval => { - let bankFrom = bankIntervals[i].from; - let bankTo = bankIntervals[i].to; - if ((Math.min(bankFrom, bankTo) < Math.max(interval.from, interval.to)) && - ((Math.min(interval.from, interval.to) < - Math.max(bankFrom, bankTo)))) { - frendsInterval[interval.name].push({ - from: Math.max(bankFrom, interval.from), - to: Math.min(bankTo, interval.to), - name: interval.name - }); - } - - }); - - }); - - let maxFrom; - let minTo; - frendsInterval.Danny.forEach(iD => { - - maxFrom = Math.max(maxFrom, iD.from); - minTo = Math.min(minTo, iD.to); - - frendsInterval.Rusty.forEach(iR => { - - maxFrom = Math.max(iD.from, iR.from); - minTo = Math.min(iD.to, iR.to); - - frendsInterval.Linus.forEach(iL => { - maxFrom = Math.max(maxFrom, iL.from); - minTo = Math.min(minTo, iL.to); - - if ((maxFrom < minTo) && (minTo - maxFrom) >= duration) { - - profit.push({ - from: maxFrom + 300, - to: minTo + 300, - day: i + 1 - }); - } - - }); - - }); - }); - } + timeLine = returnInterval(timeLine, bankIntervals, 1); + timeLine = returnInterval(timeLine, friends, 0); + let lastStart = getProfitInterval(0); return { exists() { - if (profit.length > 0) { - + if (getProfitInterval(lastStart) > 0) { return true; } return false; }, format(template) { - let resObj; - if (profit.length === 0 && !isTryLater) { + let timeStart = getProfitInterval(lastStart); + if (!timeStart) { return ''; - } else if (profit.length > 0) { - resObj = intervalToString(profit[0].from); - } else { - resObj = intervalToString(lastInterval.from); } + let tmp = intervalToString(timeStart); - return template.replace('%DD', resObj.DD).replace('%HH', resObj.HH) - .replace('%MM', resObj.MM); - + return template + .replace('%DD', tmp.DD) + .replace('%HH', tmp.HH) + .replace('%MM', tmp.MM); }, - tryLater: function () { - isTryLater = true; - if (profit.length > 0) { - return calcNextMoment(profit[0]); + tryLater() { + let nextInterval = getProfitInterval(lastStart + 30); + if (nextInterval > 0) { + lastStart = nextInterval; + return true; } return false; } }; - function calcNextMoment() { - lastInterval = JSON.parse(JSON.stringify(profit[0])); - profit[0].from = profit[0].from + 30; - if (profit[0].to - profit[0].from < duration) { - profit.splice(0, 1); - } - if (profit.length > 0) { + function getFriendsIntervals() { + let arr = []; + Object.keys(schedule).forEach(key => { + schedule[key].forEach(el => { + arr.push({ + from: timeConverter(el.from), + to: timeConverter(el.to) + }); - return true; + }); + + }); + + return arr; + } + + function getProfitInterval(from) { + let starts = []; + let start = timeLine.indexOf(1, from); + let stop = timeLine.indexOf(0, start); + while ((start !== -1)) { + if (stop - start >= duration) { + starts.push(start); + } + start = timeLine.indexOf(1, stop); + stop = timeLine.indexOf(0, start); + + } + if (starts.length === 0) { + return false; } - return false; + return starts[0]; } + }; function timeConverter(T) { - const DAYS = { - 'ПН': 0, - 'ВТ': 1440, - 'СР': 2880 - }; let timeArr = T.replace(/[+:]/ig, ' ').split(' '); - return Number(DAYS[timeArr[0]]) + Number(timeArr[1]) * 60 - + return Number(DAYS_WEEK[timeArr[0]]) + Number(timeArr[1]) * 60 - Number(timeArr[3]) * 60 + Number(timeArr[2]); } @@ -159,31 +105,31 @@ function mathIntervalsBank(obj) { }, { from: timeConverter('СР ' + obj.from), to: timeConverter('СР ' + obj.to) - } - ]; + }]; + } function intervalToString(go) { - let resObj = {}; + go = go + 300; + let objTime = {}; let mins; let time = String(go / 1440).split('.')[0]; - if (time === '0') { - resObj.DD = 'ПН'; + objTime.DD = 'ПН'; mins = go; } else if (time === '1') { - resObj.DD = 'ВТ'; + objTime.DD = 'ВТ'; mins = go - 1440; } else if (time === '2') { - resObj.DD = 'СР'; + objTime.DD = 'СР'; mins = go - 2880; } - let hoursArr = (mins / 60).toFixed(1).split('.'); - resObj.HH = twoSign(hoursArr[0]); - resObj.MM = twoSign(hoursArr[1] * 6); + let [hour, min] = (mins / 60).toFixed(1).split('.'); + objTime.HH = twoSign(hour); + objTime.MM = twoSign(min * 6); - return resObj; + return objTime; } function twoSign(num) { @@ -192,5 +138,14 @@ function twoSign(num) { } return '0' + num; +} + +function returnInterval(arr, obj, val) { + obj.forEach(el => { + for (var i = el.from; i < el.to; i++) { + arr[i] = val; + } + }); + return arr; } From d65e551e6f9c21766e377c3abdadca1775fc91d2 Mon Sep 17 00:00:00 2001 From: Medvedev Denis Date: Sun, 22 Oct 2017 21:47:14 +0500 Subject: [PATCH 4/5] =?UTF-8?q?=D0=91=D0=B5=D0=B7=20=D0=B7=D0=B2=D0=B5?= =?UTF-8?q?=D0=B7=D0=B4=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/robbery.js b/robbery.js index 029debb..d3fc114 100644 --- a/robbery.js +++ b/robbery.js @@ -1,6 +1,6 @@ 'use strict'; -exports.isStar = true; +exports.isStar = false; const DAYS_WEEK = { 'ПН': 0, 'ВТ': 1440, From 6764b6708a25de0d48f2302c8a2542a5be2497d0 Mon Sep 17 00:00:00 2001 From: Medvedev Denis Date: Mon, 23 Oct 2017 23:19:06 +0500 Subject: [PATCH 5/5] Fixed v1.0 --- package-lock.json | 16 ++++++++-------- robbery.js | 31 +++++++++++++------------------ 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6087ec1..2b4e704 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1029,14 +1029,6 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -1046,6 +1038,14 @@ "strip-ansi": "4.0.0" } }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", diff --git a/robbery.js b/robbery.js index d3fc114..04e3e48 100644 --- a/robbery.js +++ b/robbery.js @@ -1,6 +1,6 @@ 'use strict'; -exports.isStar = false; +exports.isStar = true; const DAYS_WEEK = { 'ПН': 0, 'ВТ': 1440, @@ -11,27 +11,27 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) { from: 0, to: 4320 }], 0); + let friends = getFriendsIntervals(); + let bankIntervals = mathIntervalsBank(workingHours); timeLine = returnInterval(timeLine, bankIntervals, 1); + timeLine = returnInterval(timeLine, friends, 0); - let lastStart = getProfitInterval(0); + + let currentTime = getProfitInterval(0); return { exists() { - if (getProfitInterval(lastStart) > 0) { - return true; - } - - return false; + return currentTime; }, format(template) { - let timeStart = getProfitInterval(lastStart); - if (!timeStart) { + if (!currentTime) { return ''; } - let tmp = intervalToString(timeStart); + + let tmp = intervalToString(getProfitInterval(currentTime)); return template .replace('%DD', tmp.DD) @@ -40,9 +40,9 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) { }, tryLater() { - let nextInterval = getProfitInterval(lastStart + 30); + let nextInterval = getProfitInterval(currentTime + 30); if (nextInterval > 0) { - lastStart = nextInterval; + currentTime = nextInterval; return true; } @@ -59,9 +59,7 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) { from: timeConverter(el.from), to: timeConverter(el.to) }); - }); - }); return arr; @@ -79,11 +77,8 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) { stop = timeLine.indexOf(0, start); } - if (starts.length === 0) { - return false; - } - return starts[0]; + return starts.length === 0 ? false : starts[0]; } };