From bb0bbc3f089a77b103fac493ab0267cba9823040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D0=B8=D0=BF=D0=BF=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=87=20=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= Date: Wed, 26 Oct 2016 22:52:47 +0500 Subject: [PATCH 01/35] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D1=8B=D0=B9=20?= =?UTF-8?q?=D0=B2=D0=B0=D1=80=D0=B8=D0=B0=D0=BD=D1=82=20=D1=80=D0=B5=D1=88?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 228 insertions(+), 2 deletions(-) diff --git a/robbery.js b/robbery.js index 4a8309d..cf68fb9 100644 --- a/robbery.js +++ b/robbery.js @@ -4,7 +4,9 @@ * Сделано задание на звездочку * Реализовано оба метода и tryLater */ -exports.isStar = true; +exports.isStar = false; + +var baseTimeZone = 0; // временная зона банка /** * @param {Object} schedule – Расписание Банды @@ -15,16 +17,23 @@ exports.isStar = true; * @returns {Object} */ exports.getAppropriateMoment = function (schedule, duration, workingHours) { + baseTimeZone = getBaseTimeZone(workingHours); console.info(schedule, duration, workingHours); + var robberyEvent = tryRobABank(schedule, duration, workingHours); return { + + ready: robberyEvent.ready, + day: robberyEvent.day, + hours: robberyEvent.hours, + minutes: robberyEvent.minutes, /** * Найдено ли время * @returns {Boolean} */ exists: function () { - return false; + return this.ready; }, /** @@ -35,6 +44,13 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) { * @returns {String} */ format: function (template) { + if (!this.ready) { + return ''; + } + template = template.replace('%DD', this.day); + template = template.replace('%HH', this.hours); + template = template.replace('%MM', this.minutes); + return template; }, @@ -48,3 +64,213 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) { } }; }; + +var dayTimePattern = /(([ПНВТСР]+) )?(\d+):(\d+)([+-]\d+)/i; + +function getBaseTimeZone(workingHours) { + return parseInt(dayTimePattern.exec(workingHours.from)[5], 10); +} + +var robberyEventTemplate = { + ready: false, + day: undefined, + hours: undefined, + minutes: undefined, + toString: function() { + return '{ ' + this.day + ' ' + this.hours + ':' + this.minutes + ' }'; + } +}; +var rangeTemplate = { + from: undefined, + to: undefined, + toString: function() { + return '{ from: ' + this.from + ' to: ' + this.to + ' }'; + } +}; +// Диапазоны времени когда грабители могут пойти на ограбление +var robberyRanges = { + Danny: [], + Rusty: [], + Linus: [], + Gang: [] +}; + +function tryRobABank(schedule, duration, workingHours) { + var robberyEvent = new Object(robberyEventTemplate); + // Высчитываем диапазоны, когда грабители могут пойти на ограбление + parseGangRanges(schedule); + // Фильруем диапазоны исходя из часов работы банка + filterRobberyRanges(workingHours); + // Делаем пересечение всех диапазонов всех грабителей с учётом + // времени работы банка (все готовы и банк открыт) + robberyRanges.Gang = getCrossedRanges(); + // Из готовых диапазонов получаем время, когда можно ограбить банк + // с учётом продолжительности ограбления (если вообще можно) + var robberyTime = getRobberyTime(duration); + if (robberyTime !== undefined) { + // Заполняем все поля объекта, хранящего информацию о том, когда + // и во сколько можно совершить ограбление + fillRobberyEventValues(robberyEvent, robberyTime); + } + + return robberyEvent; +} + +function parseGangRanges(schedule) { + robberyRanges.Danny.splice(0); + robberyRanges.Rusty.splice(0); + robberyRanges.Linus.splice(0); + parseRanges(schedule.Danny, robberyRanges.Danny); + parseRanges(schedule.Rusty, robberyRanges.Rusty); + parseRanges(schedule.Linus, robberyRanges.Linus); +} + +function filterRobberyRanges(workingHours) { + robberyRanges.Danny = getFilteredSchedule(workingHours, robberyRanges.Danny); + robberyRanges.Rusty = getFilteredSchedule(workingHours, robberyRanges.Rusty); + robberyRanges.Linus = getFilteredSchedule(workingHours, robberyRanges.Linus); +} + +// Высчитываем диапазоны, когда грабитель может совершить ограбление +// без учёта времени работы банка +function parseRanges(schedule, robberRanges) { + var range; + var from = 0; + var to = 0; + for (var i = 0; i < schedule.length; i++) { + if (i == 0) { + from = 0; + to = dateToMinutes(schedule[i].from); + } + if (i > 0) { + from = dateToMinutes(schedule[i - 1].to); + to = dateToMinutes(schedule[i].from); + } + range = Object.create(rangeTemplate); + range.from = from; + range.to = to; + robberRanges.push(range); + } + from = dateToMinutes(schedule[schedule.length - 1].to); + to = 24 * 60 * 3; + range = Object.create(rangeTemplate); + range.from = from; + range.to = to; + robberRanges.push(range); +} + +// Считаем количество минут, прошедших с ПН 00:00+(ЧасовойПоясБанка) +// Например, СР 15:00+3 -> 3900 (2880 прошло с ПН по ВТ 00:00 и 17 часов = 1020) +function dateToMinutes(date) { + date = date.toLowerCase(); + var minutes = 0; + if (date.startsWith('вт')) { + minutes += 24 * 60; + } + if (date.startsWith('ср')) { + minutes += 24 * 60 * 2; + } + var timeZoneOffset = baseTimeZone - parseInt(dayTimePattern.exec(date)[5], 10); + minutes += (parseInt(dayTimePattern.exec(date)[3], 10) + timeZoneOffset) * 60; + minutes += parseInt(dayTimePattern.exec(date)[4], 10); + + return minutes; +} + +// Фильтруем диапазоны свободного времени грабителя исходя из времени работы банка +function getFilteredSchedule(workingHours, schedule) { + var minutesFrom = parseInt(dayTimePattern.exec(workingHours.from)[3], 10) * 60; + minutesFrom += parseInt(dayTimePattern.exec(workingHours.from)[4], 10); + var minutesTo = parseInt(dayTimePattern.exec(workingHours.to)[3], 10) * 60; + minutesTo += parseInt(dayTimePattern.exec(workingHours.to)[4], 10); + var filteredRanges = []; + for (var ranges = 0; ranges < schedule.length; ranges++) { + for (var days = 0; days < 3; days++) { + var from = minutesFrom + days * 24 * 60; + var to = minutesTo + days * 24 * 60; + filterRange(schedule[ranges], from, to, filteredRanges); + } + } + schedule.splice(0); + + return filteredRanges; +} + +function filterRange(range, from, to, filteredRanges) { + if (range.from > to || range.to < from) { + return; + } + var maxFrom = Math.max(range.from, from); + var minTo = Math.min(range.to, to); + var newRange = Object.create(rangeTemplate); + newRange.from = maxFrom; + newRange.to = minTo; + filteredRanges.push(newRange); +} + +// Строит пересечение всех диапазонов всех троих грабителей, когда они +// могут совершить ограбление +function getCrossedRanges() { + var crossedRanges = crossTwoArraysOfRanges(robberyRanges.Danny, robberyRanges.Rusty); + crossedRanges = crossTwoArraysOfRanges(crossedRanges, robberyRanges.Linus); + + return crossedRanges; +} + +// Находит все общие диапазоны, когда граюители могут совершить ограбление +function crossTwoArraysOfRanges(firstRanges, secondRanges) { + var crossedRanges = []; + for (var i = 0; i < firstRanges.length; i++) { + for (var j = 0; j < secondRanges.length; j++) { + crossTwoRanges(firstRanges[i], secondRanges[j], crossedRanges); + } + } + + return crossedRanges; +} + +// Находим общий промежуток времени двух диапазонов, когда грабители могут +// совершить ограбление и добавляем этот диапазон в массив crossedRanges +function crossTwoRanges(firstRange, secondRange, crossedRanges) { + if (firstRange.from > secondRange.to || firstRange.to < secondRange.from) { + return; + } + var maxFrom = Math.max(firstRange.from, secondRange.from); + var minTo = Math.min(firstRange.to, secondRange.to); + var newRange = Object.create(rangeTemplate); + newRange.from = maxFrom; + newRange.to = minTo; + crossedRanges.push(newRange); +} + +// Вернёт количество минут, считая с ПН 00:00 до момента, когда можно +// совершить ограбление, либо undefined +function getRobberyTime(duration) { + for (var i = 0; i < robberyRanges.Gang.length; i++) { + var range = robberyRanges.Gang[i]; + if (range.to - range.from >= duration) { + return range.from; + } + } + + return undefined; +} + +// Преобразуем количество минут, считая с ПН 00:00 до момента, когда можно +// совершить ограбление и заполняем поля объекта robberyEvent +function fillRobberyEventValues(robberyEvent, robberyTime) { + robberyEvent.ready = true; + robberyEvent.day = 'ПН'; + if (robberyTime >= 24 * 60) { + robberyTime -= 24 * 60; + robberyEvent.day = 'ВТ'; + } + if (robberyTime >= 24 * 60 * 2) { + robberyTime -= 24 * 60; + robberyEvent.day = 'СР'; + } + var hours = Math.floor(robberyTime / 60); + robberyEvent.hours = (hours < 10) ? '0' + hours : hours; + var minutes = robberyTime % 60; + robberyEvent.minutes = (minutes < 10) ? '0' + minutes : minutes; +} From e24fda2b8bb56183930459045bad939eccb89b56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D0=B8=D0=BF=D0=BF=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=87=20=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= Date: Wed, 26 Oct 2016 23:07:54 +0500 Subject: [PATCH 02/35] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=BB=D0=B8=D0=BD=D1=82=D0=B8=D0=BD=D0=B3=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/robbery.js b/robbery.js index cf68fb9..a979c57 100644 --- a/robbery.js +++ b/robbery.js @@ -22,7 +22,7 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) { var robberyEvent = tryRobABank(schedule, duration, workingHours); return { - + ready: robberyEvent.ready, day: robberyEvent.day, hours: robberyEvent.hours, @@ -75,17 +75,11 @@ var robberyEventTemplate = { ready: false, day: undefined, hours: undefined, - minutes: undefined, - toString: function() { - return '{ ' + this.day + ' ' + this.hours + ':' + this.minutes + ' }'; - } + minutes: undefined }; var rangeTemplate = { from: undefined, - to: undefined, - toString: function() { - return '{ from: ' + this.from + ' to: ' + this.to + ' }'; - } + to: undefined }; // Диапазоны времени когда грабители могут пойти на ограбление var robberyRanges = { @@ -96,7 +90,7 @@ var robberyRanges = { }; function tryRobABank(schedule, duration, workingHours) { - var robberyEvent = new Object(robberyEventTemplate); + var robberyEvent = Object.create(robberyEventTemplate); // Высчитываем диапазоны, когда грабители могут пойти на ограбление parseGangRanges(schedule); // Фильруем диапазоны исходя из часов работы банка @@ -133,30 +127,27 @@ function filterRobberyRanges(workingHours) { // Высчитываем диапазоны, когда грабитель может совершить ограбление // без учёта времени работы банка -function parseRanges(schedule, robberRanges) { - var range; +function parseRanges(schedule, robberyRanges) { var from = 0; var to = 0; for (var i = 0; i < schedule.length; i++) { - if (i == 0) { - from = 0; - to = dateToMinutes(schedule[i].from); - } - if (i > 0) { - from = dateToMinutes(schedule[i - 1].to); + if (i === 0 || i > 0) { + from = (i === 0) ? 0 : dateToMinutes(schedule[i - 1].to); to = dateToMinutes(schedule[i].from); } - range = Object.create(rangeTemplate); - range.from = from; - range.to = to; - robberRanges.push(range); + robberyRanges.push(getRangeObject(from, to)); } from = dateToMinutes(schedule[schedule.length - 1].to); to = 24 * 60 * 3; - range = Object.create(rangeTemplate); + robberyRanges.push(getRangeObject(from, to)); +} + +function getRangeObject(from, to) { + var range = Object.create(rangeTemplate); range.from = from; range.to = to; - robberRanges.push(range); + + return range; } // Считаем количество минут, прошедших с ПН 00:00+(ЧасовойПоясБанка) From 48e35ffd899f0233f52029372c88ad5a6a81539c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D0=B8=D0=BF=D0=BF=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=87=20=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= Date: Wed, 26 Oct 2016 23:10:45 +0500 Subject: [PATCH 03/35] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=BE=20=D0=B8=D0=BC=D1=8F=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=BD=D0=BE=D0=B9=20=D0=B2=20?= =?UTF-8?q?=D0=B0=D1=80=D0=B3=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B5=20=D1=84?= =?UTF-8?q?=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/robbery.js b/robbery.js index a979c57..941cf42 100644 --- a/robbery.js +++ b/robbery.js @@ -127,7 +127,7 @@ function filterRobberyRanges(workingHours) { // Высчитываем диапазоны, когда грабитель может совершить ограбление // без учёта времени работы банка -function parseRanges(schedule, robberyRanges) { +function parseRanges(schedule, robberRanges) { var from = 0; var to = 0; for (var i = 0; i < schedule.length; i++) { @@ -135,11 +135,11 @@ function parseRanges(schedule, robberyRanges) { from = (i === 0) ? 0 : dateToMinutes(schedule[i - 1].to); to = dateToMinutes(schedule[i].from); } - robberyRanges.push(getRangeObject(from, to)); + robberRanges.push(getRangeObject(from, to)); } from = dateToMinutes(schedule[schedule.length - 1].to); to = 24 * 60 * 3; - robberyRanges.push(getRangeObject(from, to)); + robberRanges.push(getRangeObject(from, to)); } function getRangeObject(from, to) { From f3c52469c0245fa92028801a7022fff16a4cb20d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D0=B8=D0=BF=D0=BF=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=87=20=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= Date: Wed, 26 Oct 2016 23:58:05 +0500 Subject: [PATCH 04/35] robbery.js update --- robbery.js | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/robbery.js b/robbery.js index 941cf42..6afce2d 100644 --- a/robbery.js +++ b/robbery.js @@ -47,11 +47,11 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) { if (!this.ready) { return ''; } - template = template.replace('%DD', this.day); - template = template.replace('%HH', this.hours); - template = template.replace('%MM', this.minutes); - return template; + return template + .replace('%DD', this.day) + .replace('%HH', this.hours) + .replace('%MM', this.minutes); }, /** @@ -193,22 +193,27 @@ function filterRange(range, from, to, filteredRanges) { } var maxFrom = Math.max(range.from, from); var minTo = Math.min(range.to, to); - var newRange = Object.create(rangeTemplate); - newRange.from = maxFrom; - newRange.to = minTo; - filteredRanges.push(newRange); + filteredRanges.push(getRangeObject(maxFrom, minTo)); } -// Строит пересечение всех диапазонов всех троих грабителей, когда они +// Строит пересечение всех диапазонов времени всех троих грабителей, когда они // могут совершить ограбление function getCrossedRanges() { var crossedRanges = crossTwoArraysOfRanges(robberyRanges.Danny, robberyRanges.Rusty); - crossedRanges = crossTwoArraysOfRanges(crossedRanges, robberyRanges.Linus); + crossedRanges = crossTwoArraysOfRanges(crossedRanges, robberyRanges.Linus).sort(function (a, b) { + if (a.from > b.from) { + return 1; + } + if (a.from < b.from) { + return -1; + } + return 0; + }); return crossedRanges; } -// Находит все общие диапазоны, когда граюители могут совершить ограбление +// Находит все общие диапазоны, когда грабители могут совершить ограбление function crossTwoArraysOfRanges(firstRanges, secondRanges) { var crossedRanges = []; for (var i = 0; i < firstRanges.length; i++) { @@ -228,10 +233,7 @@ function crossTwoRanges(firstRange, secondRange, crossedRanges) { } var maxFrom = Math.max(firstRange.from, secondRange.from); var minTo = Math.min(firstRange.to, secondRange.to); - var newRange = Object.create(rangeTemplate); - newRange.from = maxFrom; - newRange.to = minTo; - crossedRanges.push(newRange); + crossedRanges.push(getRangeObject(maxFrom, minTo)); } // Вернёт количество минут, считая с ПН 00:00 до момента, когда можно @@ -260,8 +262,8 @@ function fillRobberyEventValues(robberyEvent, robberyTime) { robberyTime -= 24 * 60; robberyEvent.day = 'СР'; } - var hours = Math.floor(robberyTime / 60); - robberyEvent.hours = (hours < 10) ? '0' + hours : hours; var minutes = robberyTime % 60; robberyEvent.minutes = (minutes < 10) ? '0' + minutes : minutes; + var hours = (robberyTime - minutes) / 60; + robberyEvent.hours = (hours < 10) ? '0' + hours : hours; } From 88b4a8ef96634eef7e9530317e8dd0a7a9cf41c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D0=B8=D0=BF=D0=BF=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=87=20=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= Date: Thu, 27 Oct 2016 00:00:47 +0500 Subject: [PATCH 05/35] robbey.js update --- robbery.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/robbery.js b/robbery.js index 6afce2d..4f3e658 100644 --- a/robbery.js +++ b/robbery.js @@ -200,13 +200,15 @@ function filterRange(range, from, to, filteredRanges) { // могут совершить ограбление function getCrossedRanges() { var crossedRanges = crossTwoArraysOfRanges(robberyRanges.Danny, robberyRanges.Rusty); - crossedRanges = crossTwoArraysOfRanges(crossedRanges, robberyRanges.Linus).sort(function (a, b) { + crossedRanges = crossTwoArraysOfRanges(crossedRanges, robberyRanges.Linus) + .sort(function (a, b) { if (a.from > b.from) { return 1; } if (a.from < b.from) { return -1; } + return 0; }); From 26104825643c7e177435bbaa8666da0711b667fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D0=B8=D0=BF=D0=BF=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=87=20=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= Date: Sat, 29 Oct 2016 12:44:25 +0500 Subject: [PATCH 06/35] robbery.js update --- robbery.js | 147 ++++++++++++++++++++++++++--------------------------- 1 file changed, 71 insertions(+), 76 deletions(-) diff --git a/robbery.js b/robbery.js index 4f3e658..79b2cf3 100644 --- a/robbery.js +++ b/robbery.js @@ -18,7 +18,7 @@ var baseTimeZone = 0; // временная зона банка */ exports.getAppropriateMoment = function (schedule, duration, workingHours) { baseTimeZone = getBaseTimeZone(workingHours); - console.info(schedule, duration, workingHours); + //console.info(schedule, duration, workingHours); var robberyEvent = tryRobABank(schedule, duration, workingHours); return { @@ -77,9 +77,13 @@ var robberyEventTemplate = { hours: undefined, minutes: undefined }; +// Шаблон объекта для диапазонов времени var rangeTemplate = { from: undefined, - to: undefined + to: undefined, + toString: function() { + return '{ from: ' + this.from + ' to: ' + this.to + ' }'; + } }; // Диапазоны времени когда грабители могут пойти на ограбление var robberyRanges = { @@ -93,11 +97,11 @@ function tryRobABank(schedule, duration, workingHours) { var robberyEvent = Object.create(robberyEventTemplate); // Высчитываем диапазоны, когда грабители могут пойти на ограбление parseGangRanges(schedule); - // Фильруем диапазоны исходя из часов работы банка - filterRobberyRanges(workingHours); - // Делаем пересечение всех диапазонов всех грабителей с учётом - // времени работы банка (все готовы и банк открыт) - robberyRanges.Gang = getCrossedRanges(); + // Составляем диапазоны времени работы банка + var bankSchedule = getBankSchedule(workingHours); + // Делаем пересечение всех диапазонов свободного времени грабителей + // и времени работы банка + robberyRanges.Gang = getGangCrossedRanges(bankSchedule); // Из готовых диапазонов получаем время, когда можно ограбить банк // с учётом продолжительности ограбления (если вообще можно) var robberyTime = getRobberyTime(duration); @@ -119,15 +123,10 @@ function parseGangRanges(schedule) { parseRanges(schedule.Linus, robberyRanges.Linus); } -function filterRobberyRanges(workingHours) { - robberyRanges.Danny = getFilteredSchedule(workingHours, robberyRanges.Danny); - robberyRanges.Rusty = getFilteredSchedule(workingHours, robberyRanges.Rusty); - robberyRanges.Linus = getFilteredSchedule(workingHours, robberyRanges.Linus); -} - // Высчитываем диапазоны, когда грабитель может совершить ограбление // без учёта времени работы банка function parseRanges(schedule, robberRanges) { + schedule.sort(scheduleComparator); var from = 0; var to = 0; for (var i = 0; i < schedule.length; i++) { @@ -142,75 +141,24 @@ function parseRanges(schedule, robberRanges) { robberRanges.push(getRangeObject(from, to)); } -function getRangeObject(from, to) { - var range = Object.create(rangeTemplate); - range.from = from; - range.to = to; - - return range; -} - -// Считаем количество минут, прошедших с ПН 00:00+(ЧасовойПоясБанка) -// Например, СР 15:00+3 -> 3900 (2880 прошло с ПН по ВТ 00:00 и 17 часов = 1020) -function dateToMinutes(date) { - date = date.toLowerCase(); - var minutes = 0; - if (date.startsWith('вт')) { - minutes += 24 * 60; - } - if (date.startsWith('ср')) { - minutes += 24 * 60 * 2; - } - var timeZoneOffset = baseTimeZone - parseInt(dayTimePattern.exec(date)[5], 10); - minutes += (parseInt(dayTimePattern.exec(date)[3], 10) + timeZoneOffset) * 60; - minutes += parseInt(dayTimePattern.exec(date)[4], 10); - - return minutes; -} - -// Фильтруем диапазоны свободного времени грабителя исходя из времени работы банка -function getFilteredSchedule(workingHours, schedule) { - var minutesFrom = parseInt(dayTimePattern.exec(workingHours.from)[3], 10) * 60; - minutesFrom += parseInt(dayTimePattern.exec(workingHours.from)[4], 10); - var minutesTo = parseInt(dayTimePattern.exec(workingHours.to)[3], 10) * 60; - minutesTo += parseInt(dayTimePattern.exec(workingHours.to)[4], 10); - var filteredRanges = []; - for (var ranges = 0; ranges < schedule.length; ranges++) { - for (var days = 0; days < 3; days++) { - var from = minutesFrom + days * 24 * 60; - var to = minutesTo + days * 24 * 60; - filterRange(schedule[ranges], from, to, filteredRanges); - } +function getBankSchedule(workingHours) { + var schedule = []; + var days = ['ПН', 'ВТ', 'СР']; + for (var day = 0; day < days.length; day++) { + var from = dateToMinutes(days[day] + ' ' + workingHours.from); + var to = dateToMinutes(days[day] + ' ' + workingHours.to); + schedule.push(getRangeObject(from, to)); } - schedule.splice(0); - - return filteredRanges; -} -function filterRange(range, from, to, filteredRanges) { - if (range.from > to || range.to < from) { - return; - } - var maxFrom = Math.max(range.from, from); - var minTo = Math.min(range.to, to); - filteredRanges.push(getRangeObject(maxFrom, minTo)); + return schedule; } // Строит пересечение всех диапазонов времени всех троих грабителей, когда они -// могут совершить ограбление -function getCrossedRanges() { +// могут совершить ограбление и времени работы банка +function getGangCrossedRanges(bankSchedule) { var crossedRanges = crossTwoArraysOfRanges(robberyRanges.Danny, robberyRanges.Rusty); - crossedRanges = crossTwoArraysOfRanges(crossedRanges, robberyRanges.Linus) - .sort(function (a, b) { - if (a.from > b.from) { - return 1; - } - if (a.from < b.from) { - return -1; - } - - return 0; - }); + crossedRanges = crossTwoArraysOfRanges(crossedRanges, robberyRanges.Linus); + crossedRanges = crossTwoArraysOfRanges(crossedRanges, bankSchedule); return crossedRanges; } @@ -238,6 +186,53 @@ function crossTwoRanges(firstRange, secondRange, crossedRanges) { crossedRanges.push(getRangeObject(maxFrom, minTo)); } +function getRangeObject(from, to) { + var range = Object.create(rangeTemplate); + range.from = from; + range.to = to; + + return range; +} + +function scheduleComparator(first, second) { + var firstFrom = dateToMinutes(first.from); + var secondFrom = dateToMinutes(second.from); + if (firstFrom > secondFrom) { + return 1; + } + if (firstFrom < secondFrom) { + return -1; + } + var firstTo = dateToMinutes(first.to); + var secondTo = dateToMinutes(second.to); + if (firstTo > secondTo) { + return 1; + } + if (firstTo < secondTo) { + return -1; + } + + return 0; +} + +// Считаем количество минут, прошедших с ПН 00:00+(Часовой Пояс Банка) +// Например, СР 15:00+3 -> 3900 (2880 прошло с ПН по ВТ 00:00 и 17 часов = 1020) +function dateToMinutes(date) { + date = date.toLowerCase(); + var minutes = 0; + if (date.startsWith('вт')) { + minutes += 24 * 60; + } + if (date.startsWith('ср')) { + minutes += 24 * 60 * 2; + } + var timeZoneOffset = baseTimeZone - parseInt(dayTimePattern.exec(date)[5], 10); + minutes += (parseInt(dayTimePattern.exec(date)[3], 10) + timeZoneOffset) * 60; + minutes += parseInt(dayTimePattern.exec(date)[4], 10); + + return minutes; +} + // Вернёт количество минут, считая с ПН 00:00 до момента, когда можно // совершить ограбление, либо undefined function getRobberyTime(duration) { From 91f4e53e3feeac26a240d41483555492e6989a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D0=B8=D0=BF=D0=BF=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=87=20=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= Date: Sat, 29 Oct 2016 12:47:01 +0500 Subject: [PATCH 07/35] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=BB=D0=B8=D0=BD=D1=82=D0=B8=D0=BD=D0=B3=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/robbery.js b/robbery.js index 79b2cf3..2690f85 100644 --- a/robbery.js +++ b/robbery.js @@ -18,7 +18,7 @@ var baseTimeZone = 0; // временная зона банка */ exports.getAppropriateMoment = function (schedule, duration, workingHours) { baseTimeZone = getBaseTimeZone(workingHours); - //console.info(schedule, duration, workingHours); + console.info(schedule, duration, workingHours); var robberyEvent = tryRobABank(schedule, duration, workingHours); return { @@ -80,10 +80,7 @@ var robberyEventTemplate = { // Шаблон объекта для диапазонов времени var rangeTemplate = { from: undefined, - to: undefined, - toString: function() { - return '{ from: ' + this.from + ' to: ' + this.to + ' }'; - } + to: undefined }; // Диапазоны времени когда грабители могут пойти на ограбление var robberyRanges = { From 90caf24790dd84ac6e69c6a4dee75f34945589a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D0=B8=D0=BF=D0=BF=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=87=20=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= Date: Sat, 29 Oct 2016 14:08:13 +0500 Subject: [PATCH 08/35] robbery.js update --- robbery.js | 50 +++++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/robbery.js b/robbery.js index 2690f85..811802d 100644 --- a/robbery.js +++ b/robbery.js @@ -6,7 +6,10 @@ */ exports.isStar = false; -var baseTimeZone = 0; // временная зона банка +var BANK_TIMEZONE = 0; // временная зона банка +var MINUTES_IN_DAY = 26 * 60; +var DATE_PATTERN = /(([БВНПРСТЧ]+) )?(\d+):(\d+)([+-]\d+)/i; +var WEEKDAYS = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС']; /** * @param {Object} schedule – Расписание Банды @@ -17,8 +20,8 @@ var baseTimeZone = 0; // временная зона банка * @returns {Object} */ exports.getAppropriateMoment = function (schedule, duration, workingHours) { - baseTimeZone = getBaseTimeZone(workingHours); - console.info(schedule, duration, workingHours); + BANK_TIMEZONE = getBaseTimeZone(workingHours); + //console.info(schedule, duration, workingHours); var robberyEvent = tryRobABank(schedule, duration, workingHours); return { @@ -65,10 +68,8 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) { }; }; -var dayTimePattern = /(([ПНВТСР]+) )?(\d+):(\d+)([+-]\d+)/i; - function getBaseTimeZone(workingHours) { - return parseInt(dayTimePattern.exec(workingHours.from)[5], 10); + return parseInt(DATE_PATTERN.exec(workingHours.from)[5], 10); } var robberyEventTemplate = { @@ -140,10 +141,9 @@ function parseRanges(schedule, robberRanges) { function getBankSchedule(workingHours) { var schedule = []; - var days = ['ПН', 'ВТ', 'СР']; - for (var day = 0; day < days.length; day++) { - var from = dateToMinutes(days[day] + ' ' + workingHours.from); - var to = dateToMinutes(days[day] + ' ' + workingHours.to); + for (var day = 0; day < WEEKDAYS.length; day++) { + var from = dateToMinutes(WEEKDAYS[day] + ' ' + workingHours.from); + var to = dateToMinutes(WEEKDAYS[day] + ' ' + workingHours.to); schedule.push(getRangeObject(from, to)); } @@ -217,19 +217,23 @@ function scheduleComparator(first, second) { function dateToMinutes(date) { date = date.toLowerCase(); var minutes = 0; - if (date.startsWith('вт')) { - minutes += 24 * 60; - } - if (date.startsWith('ср')) { - minutes += 24 * 60 * 2; - } - var timeZoneOffset = baseTimeZone - parseInt(dayTimePattern.exec(date)[5], 10); - minutes += (parseInt(dayTimePattern.exec(date)[3], 10) + timeZoneOffset) * 60; - minutes += parseInt(dayTimePattern.exec(date)[4], 10); + var dateArray = DATE_PATTERN.exec(date); + var timeZoneOffset = BANK_TIMEZONE - Number(dateArray[5]); + minutes += dayToMinutes(dateArray[0]); + minutes += (Number(dateArray[3]) + timeZoneOffset) * 60; + minutes += Number(dateArray[4]); return minutes; } +function dayToMinutes(day) { + if (WEEKDAYS.indexOf(day) !== -1) { + return Math.min(WEEKDAYS.indexOf(day) * MINUTES_IN_DAY, 2 * MINUTES_IN_DAY); + } + + return 0; +} + // Вернёт количество минут, считая с ПН 00:00 до момента, когда можно // совершить ограбление, либо undefined function getRobberyTime(duration) { @@ -248,12 +252,12 @@ function getRobberyTime(duration) { function fillRobberyEventValues(robberyEvent, robberyTime) { robberyEvent.ready = true; robberyEvent.day = 'ПН'; - if (robberyTime >= 24 * 60) { - robberyTime -= 24 * 60; + if (robberyTime >= MINUTES_IN_DAY) { + robberyTime -= MINUTES_IN_DAY; robberyEvent.day = 'ВТ'; } - if (robberyTime >= 24 * 60 * 2) { - robberyTime -= 24 * 60; + if (robberyTime >= MINUTES_IN_DAY * 2) { + robberyTime -= MINUTES_IN_DAY; robberyEvent.day = 'СР'; } var minutes = robberyTime % 60; From 2a524fbf2590d2854e3f0577c6e5c1a7feb9df74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D0=B8=D0=BF=D0=BF=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=87=20=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= Date: Sat, 29 Oct 2016 14:09:59 +0500 Subject: [PATCH 09/35] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=BB=D0=B8=D0=BD=D1=82=D0=B8=D0=BD=D0=B3=D0=B0?= 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 811802d..e979082 100644 --- a/robbery.js +++ b/robbery.js @@ -21,7 +21,7 @@ var WEEKDAYS = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС']; */ exports.getAppropriateMoment = function (schedule, duration, workingHours) { BANK_TIMEZONE = getBaseTimeZone(workingHours); - //console.info(schedule, duration, workingHours); + console.info(schedule, duration, workingHours); var robberyEvent = tryRobABank(schedule, duration, workingHours); return { From 1f781f87f90d66034aad5bde31e21c7515d1262c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D0=B8=D0=BF=D0=BF=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=87=20=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= Date: Sat, 29 Oct 2016 14:22:26 +0500 Subject: [PATCH 10/35] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= =?UTF-8?q?=20dateToMinutes()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/robbery.js b/robbery.js index e979082..3a1ecd5 100644 --- a/robbery.js +++ b/robbery.js @@ -7,7 +7,7 @@ exports.isStar = false; var BANK_TIMEZONE = 0; // временная зона банка -var MINUTES_IN_DAY = 26 * 60; +var MINUTES_IN_DAY = 24 * 60; var DATE_PATTERN = /(([БВНПРСТЧ]+) )?(\d+):(\d+)([+-]\d+)/i; var WEEKDAYS = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС']; @@ -215,11 +215,10 @@ function scheduleComparator(first, second) { // Считаем количество минут, прошедших с ПН 00:00+(Часовой Пояс Банка) // Например, СР 15:00+3 -> 3900 (2880 прошло с ПН по ВТ 00:00 и 17 часов = 1020) function dateToMinutes(date) { - date = date.toLowerCase(); var minutes = 0; var dateArray = DATE_PATTERN.exec(date); var timeZoneOffset = BANK_TIMEZONE - Number(dateArray[5]); - minutes += dayToMinutes(dateArray[0]); + minutes += dayToMinutes(dateArray[2]); minutes += (Number(dateArray[3]) + timeZoneOffset) * 60; minutes += Number(dateArray[4]); From b30bb598791453ebb200850dbe01da6407316aa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D0=B8=D0=BF=D0=BF=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=87=20=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= Date: Sat, 29 Oct 2016 14:36:03 +0500 Subject: [PATCH 11/35] robbery.js update --- robbery.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/robbery.js b/robbery.js index 3a1ecd5..1ec895e 100644 --- a/robbery.js +++ b/robbery.js @@ -222,12 +222,12 @@ function dateToMinutes(date) { minutes += (Number(dateArray[3]) + timeZoneOffset) * 60; minutes += Number(dateArray[4]); - return minutes; + return Math.min(minutes, MINUTES_IN_DAY * 3 - 1); } function dayToMinutes(day) { if (WEEKDAYS.indexOf(day) !== -1) { - return Math.min(WEEKDAYS.indexOf(day) * MINUTES_IN_DAY, 2 * MINUTES_IN_DAY); + return WEEKDAYS.indexOf(day) * MINUTES_IN_DAY; } return 0; From a5aa85feab45a76fc13b4d2f1c05964f9cff025d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D0=B8=D0=BF=D0=BF=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=87=20=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= Date: Sat, 29 Oct 2016 20:09:35 +0500 Subject: [PATCH 12/35] robbery.js update --- robbery.js | 209 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 135 insertions(+), 74 deletions(-) diff --git a/robbery.js b/robbery.js index 1ec895e..ca36236 100644 --- a/robbery.js +++ b/robbery.js @@ -79,12 +79,12 @@ var robberyEventTemplate = { minutes: undefined }; // Шаблон объекта для диапазонов времени -var rangeTemplate = { +var intervalTemplate = { from: undefined, to: undefined }; // Диапазоны времени когда грабители могут пойти на ограбление -var robberyRanges = { +var robberyIntervals = { Danny: [], Rusty: [], Linus: [], @@ -92,59 +92,126 @@ var robberyRanges = { }; function tryRobABank(schedule, duration, workingHours) { - var robberyEvent = Object.create(robberyEventTemplate); // Высчитываем диапазоны, когда грабители могут пойти на ограбление - parseGangRanges(schedule); + parseGangIntervals(schedule); // Составляем диапазоны времени работы банка var bankSchedule = getBankSchedule(workingHours); // Делаем пересечение всех диапазонов свободного времени грабителей // и времени работы банка - robberyRanges.Gang = getGangCrossedRanges(bankSchedule); + robberyIntervals.Gang = getGangCrossedIntervals(bankSchedule); // Из готовых диапазонов получаем время, когда можно ограбить банк // с учётом продолжительности ограбления (если вообще можно) var robberyTime = getRobberyTime(duration); - if (robberyTime !== undefined) { - // Заполняем все поля объекта, хранящего информацию о том, когда - // и во сколько можно совершить ограбление - fillRobberyEventValues(robberyEvent, robberyTime); - } + var robberyEvent = getRobberyEvent(robberyTime); return robberyEvent; } -function parseGangRanges(schedule) { - robberyRanges.Danny.splice(0); - robberyRanges.Rusty.splice(0); - robberyRanges.Linus.splice(0); - parseRanges(schedule.Danny, robberyRanges.Danny); - parseRanges(schedule.Rusty, robberyRanges.Rusty); - parseRanges(schedule.Linus, robberyRanges.Linus); +function parseGangIntervals(schedule) { + robberyIntervals.Danny.splice(0); + robberyIntervals.Rusty.splice(0); + robberyIntervals.Linus.splice(0); + robberyIntervals.Danny = getFreeIntervals(schedule.Danny); + robberyIntervals.Rusty = getFreeIntervals(schedule.Rusty); + robberyIntervals.Linus = getFreeIntervals(schedule.Linus); } // Высчитываем диапазоны, когда грабитель может совершить ограбление // без учёта времени работы банка -function parseRanges(schedule, robberRanges) { - schedule.sort(scheduleComparator); +function getFreeIntervals(schedule) { + var busyIntervals = getBusyIntervals(schedule); + busyIntervals.sort(intervalsComparator); + var freeIntervals = []; + var from = 0; + var to = 0; + for (var i = 0; i < busyIntervals.length; i++) { + // Если грабитель занят с в ПН 00:00, то интервала с ПН 00:00 до ПН 00:00 нет + if (i === 0 && schedule[i].from === 0) { + continue; + } + from = (i === 0) ? 0 : dateToMinutes(schedule[i - 1].to); + to = dateToMinutes(schedule[i].from); + freeIntervals.push(getInterval(from, to)); + } + // Если последний интервал, когда рабитель занят, не приходится на СР 23:59 + if (busyIntervals[busyIntervals.length - 1].to !== MINUTES_IN_DAY * 3 - 1) { + from = busyIntervals[busyIntervals.length - 1].to; + to = MINUTES_IN_DAY * 3 - 1; + freeIntervals.push(getInterval(from, to)); + } + busyIntervals.splice(0); + + return freeIntervals; +} + +function getBusyIntervals(schedule) { + var intervals = []; var from = 0; var to = 0; for (var i = 0; i < schedule.length; i++) { - if (i === 0 || i > 0) { - from = (i === 0) ? 0 : dateToMinutes(schedule[i - 1].to); - to = dateToMinutes(schedule[i].from); + from = dateToMinutes(schedule[i].from); + to = dateToMinutes(schedule[i].to); + intervals.push(getInterval(from, to)); + } + intervals.sort(intervalsComparator); + // Склеиваем пересекающиеся интервалы + mergeBusyIntervals(intervals); + + return intervals; +} + +function mergeBusyIntervals(busyIntervals) { + var mergedIntervals = []; + var handled = []; + for (var i = 0; i < busyIntervals.length; i++) { + tryToMergeInterval(busyIntervals, i, i + 1); + } +} + +function tryToMergeInterval(busyIntervals, current, next) { + for (var i = next; i < busyIntervals.length; i++) { + var mergedInterval = getMergedInterval(busyIntervals[current], busyIntervals[i]); + if (mergedInterval !== null) { + busyIntervals[current] = mergedInterval; + busyIntervals.splice(i, 1); + i--; } - robberRanges.push(getRangeObject(from, to)); } - from = dateToMinutes(schedule[schedule.length - 1].to); - to = 24 * 60 * 3; - robberRanges.push(getRangeObject(from, to)); +} + +function getMergedInterval(first, second) { + var from = 0; + var to = 0; + // Если первый содержится во втором или совпадает с ним, или + // Если второй содержится в первом или совпадает с ним + if (first.from >= second.from && first.to <= second.to || + first.from <= second.from && first.to >= second.to) { + from = Math.min(first.from, second.from); + to = Math.max(first.to, second.to); + return getInterval(from, to); + } + // Если второй пересекает первого слева + if (first.from >= second.from && first.from <= second.to) { + from = second.from; + to = first.to; + return getInterval(from, to); + } + // Если второй пересекает первого справа + if (first.to <= second.to && first.to >= second.from) { + from = first.from; + to = second.to; + return getInterval(from, to); + } + + return null; } function getBankSchedule(workingHours) { var schedule = []; - for (var day = 0; day < WEEKDAYS.length; day++) { + for (var day = 0; day < 3; day++) { var from = dateToMinutes(WEEKDAYS[day] + ' ' + workingHours.from); var to = dateToMinutes(WEEKDAYS[day] + ' ' + workingHours.to); - schedule.push(getRangeObject(from, to)); + schedule.push(getInterval(from, to)); } return schedule; @@ -152,60 +219,55 @@ function getBankSchedule(workingHours) { // Строит пересечение всех диапазонов времени всех троих грабителей, когда они // могут совершить ограбление и времени работы банка -function getGangCrossedRanges(bankSchedule) { - var crossedRanges = crossTwoArraysOfRanges(robberyRanges.Danny, robberyRanges.Rusty); - crossedRanges = crossTwoArraysOfRanges(crossedRanges, robberyRanges.Linus); - crossedRanges = crossTwoArraysOfRanges(crossedRanges, bankSchedule); +function getGangCrossedIntervals(bankSchedule) { + var crossedInterval = getCrossedIntervals(robberyIntervals.Danny, robberyIntervals.Rusty); + crossedInterval = getCrossedIntervals(crossedInterval, robberyIntervals.Linus); + crossedInterval = getCrossedIntervals(crossedInterval, bankSchedule); - return crossedRanges; + return crossedInterval; } // Находит все общие диапазоны, когда грабители могут совершить ограбление -function crossTwoArraysOfRanges(firstRanges, secondRanges) { - var crossedRanges = []; - for (var i = 0; i < firstRanges.length; i++) { - for (var j = 0; j < secondRanges.length; j++) { - crossTwoRanges(firstRanges[i], secondRanges[j], crossedRanges); +function getCrossedIntervals(firstIntervals, secondIntervals) { + var crossedIntervals = []; + for (var i = 0; i < firstIntervals.length; i++) { + for (var j = 0; j < secondIntervals.length; j++) { + crossTwoIntervals(firstIntervals[i], secondIntervals[j], crossedIntervals); } } - return crossedRanges; + return crossedIntervals; } -// Находим общий промежуток времени двух диапазонов, когда грабители могут -// совершить ограбление и добавляем этот диапазон в массив crossedRanges -function crossTwoRanges(firstRange, secondRange, crossedRanges) { - if (firstRange.from > secondRange.to || firstRange.to < secondRange.from) { +// Находим пересечение двух диапазонов времени +function crossTwoIntervals(first, second, crossedIntervals) { + if (first.from > second.to || first.to < second.from) { return; } - var maxFrom = Math.max(firstRange.from, secondRange.from); - var minTo = Math.min(firstRange.to, secondRange.to); - crossedRanges.push(getRangeObject(maxFrom, minTo)); + var maxFrom = Math.max(first.from, second.from); + var minTo = Math.min(first.to, second.to); + crossedIntervals.push(getInterval(maxFrom, minTo)); } -function getRangeObject(from, to) { - var range = Object.create(rangeTemplate); - range.from = from; - range.to = to; +function getInterval(from, to) { + var interval = Object.create(intervalTemplate); + interval.from = from; + interval.to = to; - return range; + return interval; } -function scheduleComparator(first, second) { - var firstFrom = dateToMinutes(first.from); - var secondFrom = dateToMinutes(second.from); - if (firstFrom > secondFrom) { +function intervalsComparator(first, second) { + if (first.from > second.from) { return 1; } - if (firstFrom < secondFrom) { + if (first.from < second.from) { return -1; } - var firstTo = dateToMinutes(first.to); - var secondTo = dateToMinutes(second.to); - if (firstTo > secondTo) { + if (first.to > second.to) { return 1; } - if (firstTo < secondTo) { + if (first.to < second.to) { return -1; } @@ -236,10 +298,10 @@ function dayToMinutes(day) { // Вернёт количество минут, считая с ПН 00:00 до момента, когда можно // совершить ограбление, либо undefined function getRobberyTime(duration) { - for (var i = 0; i < robberyRanges.Gang.length; i++) { - var range = robberyRanges.Gang[i]; - if (range.to - range.from >= duration) { - return range.from; + for (var i = 0; i < robberyIntervals.Gang.length; i++) { + var interval = robberyIntervals.Gang[i]; + if (interval.to - interval.from >= duration) { + return interval.from; } } @@ -248,19 +310,18 @@ function getRobberyTime(duration) { // Преобразуем количество минут, считая с ПН 00:00 до момента, когда можно // совершить ограбление и заполняем поля объекта robberyEvent -function fillRobberyEventValues(robberyEvent, robberyTime) { - robberyEvent.ready = true; - robberyEvent.day = 'ПН'; - if (robberyTime >= MINUTES_IN_DAY) { - robberyTime -= MINUTES_IN_DAY; - robberyEvent.day = 'ВТ'; - } - if (robberyTime >= MINUTES_IN_DAY * 2) { - robberyTime -= MINUTES_IN_DAY; - robberyEvent.day = 'СР'; +function getRobberyEvent(robberyTime) { + var robberyEvent = Object.create(robberyEventTemplate); + if (robberyTime === undefined) { + return robberyEvent; } + robberyEvent.ready = true; + robberyEvent.day = WEEKDAYS[Math.floor(robberyTime / MINUTES_IN_DAY)]; + robberyTime -= WEEKDAYS.indexOf(robberyEvent.day) * MINUTES_IN_DAY; var minutes = robberyTime % 60; robberyEvent.minutes = (minutes < 10) ? '0' + minutes : minutes; var hours = (robberyTime - minutes) / 60; robberyEvent.hours = (hours < 10) ? '0' + hours : hours; + + return robberyEvent; } From a712e5a4c483d8bafa93a35724316b0cdb3b927d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D0=B8=D0=BF=D0=BF=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=87=20=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= Date: Sat, 29 Oct 2016 20:16:29 +0500 Subject: [PATCH 13/35] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=BB=D0=B8=D0=BD=D1=82=D0=B8=D0=BD=D0=B3=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/robbery.js b/robbery.js index ca36236..ad980fa 100644 --- a/robbery.js +++ b/robbery.js @@ -123,23 +123,19 @@ function getFreeIntervals(schedule) { busyIntervals.sort(intervalsComparator); var freeIntervals = []; var from = 0; - var to = 0; for (var i = 0; i < busyIntervals.length; i++) { // Если грабитель занят с в ПН 00:00, то интервала с ПН 00:00 до ПН 00:00 нет - if (i === 0 && schedule[i].from === 0) { + if (i === 0 && busyIntervals[i].from === 0) { continue; } - from = (i === 0) ? 0 : dateToMinutes(schedule[i - 1].to); - to = dateToMinutes(schedule[i].from); - freeIntervals.push(getInterval(from, to)); + from = (i === 0) ? 0 : busyIntervals[i - 1].to; + freeIntervals.push(getInterval(from, busyIntervals[i].from)); } // Если последний интервал, когда рабитель занят, не приходится на СР 23:59 if (busyIntervals[busyIntervals.length - 1].to !== MINUTES_IN_DAY * 3 - 1) { from = busyIntervals[busyIntervals.length - 1].to; - to = MINUTES_IN_DAY * 3 - 1; - freeIntervals.push(getInterval(from, to)); + freeIntervals.push(getInterval(from, MINUTES_IN_DAY * 3 - 1)); } - busyIntervals.splice(0); return freeIntervals; } @@ -161,8 +157,6 @@ function getBusyIntervals(schedule) { } function mergeBusyIntervals(busyIntervals) { - var mergedIntervals = []; - var handled = []; for (var i = 0; i < busyIntervals.length; i++) { tryToMergeInterval(busyIntervals, i, i + 1); } @@ -188,18 +182,21 @@ function getMergedInterval(first, second) { first.from <= second.from && first.to >= second.to) { from = Math.min(first.from, second.from); to = Math.max(first.to, second.to); + return getInterval(from, to); } // Если второй пересекает первого слева if (first.from >= second.from && first.from <= second.to) { from = second.from; to = first.to; + return getInterval(from, to); } // Если второй пересекает первого справа if (first.to <= second.to && first.to >= second.from) { from = first.from; to = second.to; + return getInterval(from, to); } From 70b0eb04b4ae4b571c3cf4a1db4692e28578a9ad Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 31 Oct 2016 22:08:45 +0500 Subject: [PATCH 14/35] =?UTF-8?q?=D0=92=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D1=80=D0=B5=D0=BA=D0=BE=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=B4=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 75 ++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/robbery.js b/robbery.js index ad980fa..2d9ae3d 100644 --- a/robbery.js +++ b/robbery.js @@ -7,7 +7,10 @@ exports.isStar = false; var BANK_TIMEZONE = 0; // временная зона банка -var MINUTES_IN_DAY = 24 * 60; +var MINUTES_IN_HOUR = 60; +var MINUTES_IN_DAY = 24 * MINUTES_IN_HOUR; +var DAYS_FOR_ROBBERY = 3; +var MAX_MINUTES = DAYS_FOR_ROBBERY * MINUTES_IN_DAY - 1; // максимум 3 суток на ограбление и -1 минута var DATE_PATTERN = /(([БВНПРСТЧ]+) )?(\d+):(\d+)([+-]\d+)/i; var WEEKDAYS = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС']; @@ -22,7 +25,7 @@ var WEEKDAYS = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС']; exports.getAppropriateMoment = function (schedule, duration, workingHours) { BANK_TIMEZONE = getBaseTimeZone(workingHours); console.info(schedule, duration, workingHours); - var robberyEvent = tryRobABank(schedule, duration, workingHours); + var robberyEvent = tryRobBank(schedule, duration, workingHours); return { @@ -84,14 +87,9 @@ var intervalTemplate = { to: undefined }; // Диапазоны времени когда грабители могут пойти на ограбление -var robberyIntervals = { - Danny: [], - Rusty: [], - Linus: [], - Gang: [] -}; +var robberyIntervals = {}; -function tryRobABank(schedule, duration, workingHours) { +function tryRobBank(schedule, duration, workingHours) { // Высчитываем диапазоны, когда грабители могут пойти на ограбление parseGangIntervals(schedule); // Составляем диапазоны времени работы банка @@ -108,12 +106,14 @@ function tryRobABank(schedule, duration, workingHours) { } function parseGangIntervals(schedule) { - robberyIntervals.Danny.splice(0); - robberyIntervals.Rusty.splice(0); - robberyIntervals.Linus.splice(0); - robberyIntervals.Danny = getFreeIntervals(schedule.Danny); - robberyIntervals.Rusty = getFreeIntervals(schedule.Rusty); - robberyIntervals.Linus = getFreeIntervals(schedule.Linus); + var keys = Object.keys(robberyIntervals); + keys.forEach(function (robber) { + robberyIntervals[robber].splice(0); + delete robberyIntervals[robber]; + }); + for (var robber in schedule) { + robberyIntervals[robber] = getFreeIntervals(schedule[robber]); + } } // Высчитываем диапазоны, когда грабитель может совершить ограбление @@ -132,9 +132,10 @@ function getFreeIntervals(schedule) { freeIntervals.push(getInterval(from, busyIntervals[i].from)); } // Если последний интервал, когда рабитель занят, не приходится на СР 23:59 - if (busyIntervals[busyIntervals.length - 1].to !== MINUTES_IN_DAY * 3 - 1) { + // то добавляем интервал с конца рабочего времени грабителя по СР 23:59 + if (busyIntervals[busyIntervals.length - 1].to !== MAX_MINUTES) { from = busyIntervals[busyIntervals.length - 1].to; - freeIntervals.push(getInterval(from, MINUTES_IN_DAY * 3 - 1)); + freeIntervals.push(getInterval(from, MAX_MINUTES)); } return freeIntervals; @@ -217,11 +218,12 @@ function getBankSchedule(workingHours) { // Строит пересечение всех диапазонов времени всех троих грабителей, когда они // могут совершить ограбление и времени работы банка function getGangCrossedIntervals(bankSchedule) { - var crossedInterval = getCrossedIntervals(robberyIntervals.Danny, robberyIntervals.Rusty); - crossedInterval = getCrossedIntervals(crossedInterval, robberyIntervals.Linus); - crossedInterval = getCrossedIntervals(crossedInterval, bankSchedule); + var crossedIntervals = bankSchedule; + for (var robber in robberyIntervals) { + crossedIntervals = getCrossedIntervals(crossedIntervals, robberyIntervals[robber]); + } - return crossedInterval; + return crossedIntervals; } // Находит все общие диапазоны, когда грабители могут совершить ограбление @@ -255,16 +257,12 @@ function getInterval(from, to) { } function intervalsComparator(first, second) { - if (first.from > second.from) { + if (first.from > second.from || + first.from === second.from && first.to > second.to) { return 1; } - if (first.from < second.from) { - return -1; - } - if (first.to > second.to) { - return 1; - } - if (first.to < second.to) { + if (first.from < second.from || + first.from === second.from && first.to < second.to) { return -1; } @@ -274,14 +272,13 @@ function intervalsComparator(first, second) { // Считаем количество минут, прошедших с ПН 00:00+(Часовой Пояс Банка) // Например, СР 15:00+3 -> 3900 (2880 прошло с ПН по ВТ 00:00 и 17 часов = 1020) function dateToMinutes(date) { - var minutes = 0; - var dateArray = DATE_PATTERN.exec(date); - var timeZoneOffset = BANK_TIMEZONE - Number(dateArray[5]); - minutes += dayToMinutes(dateArray[2]); - minutes += (Number(dateArray[3]) + timeZoneOffset) * 60; - minutes += Number(dateArray[4]); - - return Math.min(minutes, MINUTES_IN_DAY * 3 - 1); + var timeZoneOffset = BANK_TIMEZONE - Number(DATE_PATTERN.exec(date)[5]); + var day = DATE_PATTERN.exec(date)[2]; + var hours = Number(DATE_PATTERN.exec(date)[3]) + timeZoneOffset; + var minutes = Number(DATE_PATTERN.exec(date)[4]); + var result = dayToMinutes(day) + hours * MINUTES_IN_HOUR + minutes; + + return Math.min(result, MAX_MINUTES); } function dayToMinutes(day) { @@ -315,9 +312,9 @@ function getRobberyEvent(robberyTime) { robberyEvent.ready = true; robberyEvent.day = WEEKDAYS[Math.floor(robberyTime / MINUTES_IN_DAY)]; robberyTime -= WEEKDAYS.indexOf(robberyEvent.day) * MINUTES_IN_DAY; - var minutes = robberyTime % 60; + var minutes = robberyTime % MINUTES_IN_HOUR; robberyEvent.minutes = (minutes < 10) ? '0' + minutes : minutes; - var hours = (robberyTime - minutes) / 60; + var hours = (robberyTime - minutes) / MINUTES_IN_HOUR; robberyEvent.hours = (hours < 10) ? '0' + hours : hours; return robberyEvent; From eb6e46c9de7e4932402af83e494f3e7147b3171b Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 31 Oct 2016 22:14:14 +0500 Subject: [PATCH 15/35] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/robbery.js b/robbery.js index 2d9ae3d..2b1cf6c 100644 --- a/robbery.js +++ b/robbery.js @@ -10,7 +10,7 @@ var BANK_TIMEZONE = 0; // временная зона банка var MINUTES_IN_HOUR = 60; var MINUTES_IN_DAY = 24 * MINUTES_IN_HOUR; var DAYS_FOR_ROBBERY = 3; -var MAX_MINUTES = DAYS_FOR_ROBBERY * MINUTES_IN_DAY - 1; // максимум 3 суток на ограбление и -1 минута +var MAX_MINUTES = DAYS_FOR_ROBBERY * MINUTES_IN_DAY - 1; // макс. 3 дня на ограбление и -1 минута var DATE_PATTERN = /(([БВНПРСТЧ]+) )?(\d+):(\d+)([+-]\d+)/i; var WEEKDAYS = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС']; @@ -112,7 +112,9 @@ function parseGangIntervals(schedule) { delete robberyIntervals[robber]; }); for (var robber in schedule) { - robberyIntervals[robber] = getFreeIntervals(schedule[robber]); + if (schedule.hasOwnProperty(robber)) { + robberyIntervals[robber] = getFreeIntervals(schedule[robber]); + } } } @@ -220,7 +222,9 @@ function getBankSchedule(workingHours) { function getGangCrossedIntervals(bankSchedule) { var crossedIntervals = bankSchedule; for (var robber in robberyIntervals) { - crossedIntervals = getCrossedIntervals(crossedIntervals, robberyIntervals[robber]); + if (robberyIntervals.hasOwnProperty(robber)) { + crossedIntervals = getCrossedIntervals(crossedIntervals, robberyIntervals[robber]); + } } return crossedIntervals; From 083ea985809dace5e967eeb36a9b3d9018940105 Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 31 Oct 2016 22:23:42 +0500 Subject: [PATCH 16/35] one more try --- robbery.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/robbery.js b/robbery.js index 2b1cf6c..8850225 100644 --- a/robbery.js +++ b/robbery.js @@ -220,18 +220,22 @@ function getBankSchedule(workingHours) { // Строит пересечение всех диапазонов времени всех троих грабителей, когда они // могут совершить ограбление и времени работы банка function getGangCrossedIntervals(bankSchedule) { - var crossedIntervals = bankSchedule; + var crossedIntervals = []; for (var robber in robberyIntervals) { if (robberyIntervals.hasOwnProperty(robber)) { crossedIntervals = getCrossedIntervals(crossedIntervals, robberyIntervals[robber]); } } + crossedIntervals = getCrossedIntervals(crossedIntervals, bankSchedule); return crossedIntervals; } // Находит все общие диапазоны, когда грабители могут совершить ограбление function getCrossedIntervals(firstIntervals, secondIntervals) { + if (firstIntervals.length === 0 || secondIntervals.length === 0) { + return (firstIntervals.length !== 0) ? firstIntervals : secondIntervals; + } var crossedIntervals = []; for (var i = 0; i < firstIntervals.length; i++) { for (var j = 0; j < secondIntervals.length; j++) { From 2710c6d122614caf81504d15aee3b1570319b14f Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 31 Oct 2016 22:40:38 +0500 Subject: [PATCH 17/35] =?UTF-8?q?=D0=93=D0=B8=D0=B1=D1=80=D0=B8=D0=B4=20?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=80=D0=BE=D0=B9=20=D0=B8=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D0=B9=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/robbery.js b/robbery.js index 8850225..36b9d5d 100644 --- a/robbery.js +++ b/robbery.js @@ -220,22 +220,15 @@ function getBankSchedule(workingHours) { // Строит пересечение всех диапазонов времени всех троих грабителей, когда они // могут совершить ограбление и времени работы банка function getGangCrossedIntervals(bankSchedule) { - var crossedIntervals = []; - for (var robber in robberyIntervals) { - if (robberyIntervals.hasOwnProperty(robber)) { - crossedIntervals = getCrossedIntervals(crossedIntervals, robberyIntervals[robber]); - } - } - crossedIntervals = getCrossedIntervals(crossedIntervals, bankSchedule); + var crossedInterval = getCrossedIntervals(robberyIntervals.Danny, robberyIntervals.Rusty); + crossedInterval = getCrossedIntervals(crossedInterval, robberyIntervals.Linus); + crossedInterval = getCrossedIntervals(crossedInterval, bankSchedule); - return crossedIntervals; + return crossedInterval; } // Находит все общие диапазоны, когда грабители могут совершить ограбление function getCrossedIntervals(firstIntervals, secondIntervals) { - if (firstIntervals.length === 0 || secondIntervals.length === 0) { - return (firstIntervals.length !== 0) ? firstIntervals : secondIntervals; - } var crossedIntervals = []; for (var i = 0; i < firstIntervals.length; i++) { for (var j = 0; j < secondIntervals.length; j++) { @@ -265,12 +258,16 @@ function getInterval(from, to) { } function intervalsComparator(first, second) { - if (first.from > second.from || - first.from === second.from && first.to > second.to) { + if (first.from > second.from) { return 1; } - if (first.from < second.from || - first.from === second.from && first.to < second.to) { + if (first.from < second.from) { + return -1; + } + if (first.to > second.to) { + return 1; + } + if (first.to < second.to) { return -1; } @@ -280,13 +277,14 @@ function intervalsComparator(first, second) { // Считаем количество минут, прошедших с ПН 00:00+(Часовой Пояс Банка) // Например, СР 15:00+3 -> 3900 (2880 прошло с ПН по ВТ 00:00 и 17 часов = 1020) function dateToMinutes(date) { - var timeZoneOffset = BANK_TIMEZONE - Number(DATE_PATTERN.exec(date)[5]); - var day = DATE_PATTERN.exec(date)[2]; - var hours = Number(DATE_PATTERN.exec(date)[3]) + timeZoneOffset; - var minutes = Number(DATE_PATTERN.exec(date)[4]); - var result = dayToMinutes(day) + hours * MINUTES_IN_HOUR + minutes; - - return Math.min(result, MAX_MINUTES); + var minutes = 0; + var dateArray = DATE_PATTERN.exec(date); + var timeZoneOffset = BANK_TIMEZONE - Number(dateArray[5]); + minutes += dayToMinutes(dateArray[2]); + minutes += (Number(dateArray[3]) + timeZoneOffset) * 60; + minutes += Number(dateArray[4]); + + return Math.min(minutes, MINUTES_IN_DAY * 3 - 1); } function dayToMinutes(day) { From efc10b62626ac89ec9abd193f85da2acf90e1ce4 Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 31 Oct 2016 22:43:02 +0500 Subject: [PATCH 18/35] =?UTF-8?q?=D0=93=D0=B8=D0=B1=D1=80=D0=B8=D0=B4=20?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=80=D0=BE=D0=B9=20=D0=B8=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D0=B9=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B9=20#2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 64 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/robbery.js b/robbery.js index 36b9d5d..c970af8 100644 --- a/robbery.js +++ b/robbery.js @@ -87,7 +87,12 @@ var intervalTemplate = { to: undefined }; // Диапазоны времени когда грабители могут пойти на ограбление -var robberyIntervals = {}; +var robberyIntervals = { + Danny: [], + Rusty: [], + Linus: [], + Gang: [] +}; function tryRobBank(schedule, duration, workingHours) { // Высчитываем диапазоны, когда грабители могут пойти на ограбление @@ -106,16 +111,12 @@ function tryRobBank(schedule, duration, workingHours) { } function parseGangIntervals(schedule) { - var keys = Object.keys(robberyIntervals); - keys.forEach(function (robber) { - robberyIntervals[robber].splice(0); - delete robberyIntervals[robber]; - }); - for (var robber in schedule) { - if (schedule.hasOwnProperty(robber)) { - robberyIntervals[robber] = getFreeIntervals(schedule[robber]); - } - } + robberyIntervals.Danny.splice(0); + robberyIntervals.Rusty.splice(0); + robberyIntervals.Linus.splice(0); + robberyIntervals.Danny = getFreeIntervals(schedule.Danny); + robberyIntervals.Rusty = getFreeIntervals(schedule.Rusty); + robberyIntervals.Linus = getFreeIntervals(schedule.Linus); } // Высчитываем диапазоны, когда грабитель может совершить ограбление @@ -220,15 +221,21 @@ function getBankSchedule(workingHours) { // Строит пересечение всех диапазонов времени всех троих грабителей, когда они // могут совершить ограбление и времени работы банка function getGangCrossedIntervals(bankSchedule) { - var crossedInterval = getCrossedIntervals(robberyIntervals.Danny, robberyIntervals.Rusty); - crossedInterval = getCrossedIntervals(crossedInterval, robberyIntervals.Linus); - crossedInterval = getCrossedIntervals(crossedInterval, bankSchedule); + var crossedIntervals = bankSchedule; + for (var robber in robberyIntervals) { + if (robberyIntervals.hasOwnProperty(robber)) { + crossedIntervals = getCrossedIntervals(crossedIntervals, robberyIntervals[robber]); + } + } - return crossedInterval; + return crossedIntervals; } // Находит все общие диапазоны, когда грабители могут совершить ограбление function getCrossedIntervals(firstIntervals, secondIntervals) { + if (firstIntervals.length === 0 || secondIntervals.length === 0) { + return (firstIntervals.length !== 0) ? firstIntervals : secondIntervals; + } var crossedIntervals = []; for (var i = 0; i < firstIntervals.length; i++) { for (var j = 0; j < secondIntervals.length; j++) { @@ -258,16 +265,12 @@ function getInterval(from, to) { } function intervalsComparator(first, second) { - if (first.from > second.from) { - return 1; - } - if (first.from < second.from) { - return -1; - } - if (first.to > second.to) { + if (first.from > second.from || + first.from === second.from && first.to > second.to) { return 1; } - if (first.to < second.to) { + if (first.from < second.from || + first.from === second.from && first.to < second.to) { return -1; } @@ -277,14 +280,13 @@ function intervalsComparator(first, second) { // Считаем количество минут, прошедших с ПН 00:00+(Часовой Пояс Банка) // Например, СР 15:00+3 -> 3900 (2880 прошло с ПН по ВТ 00:00 и 17 часов = 1020) function dateToMinutes(date) { - var minutes = 0; - var dateArray = DATE_PATTERN.exec(date); - var timeZoneOffset = BANK_TIMEZONE - Number(dateArray[5]); - minutes += dayToMinutes(dateArray[2]); - minutes += (Number(dateArray[3]) + timeZoneOffset) * 60; - minutes += Number(dateArray[4]); - - return Math.min(minutes, MINUTES_IN_DAY * 3 - 1); + var timeZoneOffset = BANK_TIMEZONE - Number(DATE_PATTERN.exec(date)[5]); + var day = DATE_PATTERN.exec(date)[2]; + var hours = Number(DATE_PATTERN.exec(date)[3]) + timeZoneOffset; + var minutes = Number(DATE_PATTERN.exec(date)[4]); + var result = dayToMinutes(day) + hours * MINUTES_IN_HOUR + minutes; + + return Math.min(result, MAX_MINUTES); } function dayToMinutes(day) { From cab11152a615e13377b3b45aef3e5bfe55f5229d Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 31 Oct 2016 23:05:13 +0500 Subject: [PATCH 19/35] =?UTF-8?q?=D0=93=D0=B8=D0=B1=D1=80=D0=B8=D0=B4=20?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=80=D0=BE=D0=B9=20=D0=B8=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D0=B9=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B9=20#3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/robbery.js b/robbery.js index c970af8..d163197 100644 --- a/robbery.js +++ b/robbery.js @@ -87,12 +87,7 @@ var intervalTemplate = { to: undefined }; // Диапазоны времени когда грабители могут пойти на ограбление -var robberyIntervals = { - Danny: [], - Rusty: [], - Linus: [], - Gang: [] -}; +var robberyIntervals = {}; function tryRobBank(schedule, duration, workingHours) { // Высчитываем диапазоны, когда грабители могут пойти на ограбление @@ -135,7 +130,6 @@ function getFreeIntervals(schedule) { freeIntervals.push(getInterval(from, busyIntervals[i].from)); } // Если последний интервал, когда рабитель занят, не приходится на СР 23:59 - // то добавляем интервал с конца рабочего времени грабителя по СР 23:59 if (busyIntervals[busyIntervals.length - 1].to !== MAX_MINUTES) { from = busyIntervals[busyIntervals.length - 1].to; freeIntervals.push(getInterval(from, MAX_MINUTES)); @@ -209,7 +203,7 @@ function getMergedInterval(first, second) { function getBankSchedule(workingHours) { var schedule = []; - for (var day = 0; day < 3; day++) { + for (var day = 0; day < DAYS_FOR_ROBBERY; day++) { var from = dateToMinutes(WEEKDAYS[day] + ' ' + workingHours.from); var to = dateToMinutes(WEEKDAYS[day] + ' ' + workingHours.to); schedule.push(getInterval(from, to)); @@ -221,21 +215,15 @@ function getBankSchedule(workingHours) { // Строит пересечение всех диапазонов времени всех троих грабителей, когда они // могут совершить ограбление и времени работы банка function getGangCrossedIntervals(bankSchedule) { - var crossedIntervals = bankSchedule; - for (var robber in robberyIntervals) { - if (robberyIntervals.hasOwnProperty(robber)) { - crossedIntervals = getCrossedIntervals(crossedIntervals, robberyIntervals[robber]); - } - } + var crossedInterval = getCrossedIntervals(robberyIntervals.Danny, robberyIntervals.Rusty); + crossedInterval = getCrossedIntervals(crossedInterval, robberyIntervals.Linus); + crossedInterval = getCrossedIntervals(crossedInterval, bankSchedule); - return crossedIntervals; + return crossedInterval; } // Находит все общие диапазоны, когда грабители могут совершить ограбление function getCrossedIntervals(firstIntervals, secondIntervals) { - if (firstIntervals.length === 0 || secondIntervals.length === 0) { - return (firstIntervals.length !== 0) ? firstIntervals : secondIntervals; - } var crossedIntervals = []; for (var i = 0; i < firstIntervals.length; i++) { for (var j = 0; j < secondIntervals.length; j++) { @@ -265,12 +253,16 @@ function getInterval(from, to) { } function intervalsComparator(first, second) { - if (first.from > second.from || - first.from === second.from && first.to > second.to) { + if (first.from > second.from) { + return 1; + } + if (first.from < second.from) { + return -1; + } + if (first.to > second.to) { return 1; } - if (first.from < second.from || - first.from === second.from && first.to < second.to) { + if (first.to < second.to) { return -1; } From 60278189a9af56ba3e56e0f8c5755b0393f7e8bc Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 31 Oct 2016 23:08:55 +0500 Subject: [PATCH 20/35] =?UTF-8?q?=D0=93=D0=B8=D0=B1=D1=80=D0=B8=D0=B4=20?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=80=D0=BE=D0=B9=20=D0=B8=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D0=B9=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B9=20#3?= =?UTF-8?q?=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/robbery.js b/robbery.js index d163197..dd59fd4 100644 --- a/robbery.js +++ b/robbery.js @@ -87,7 +87,12 @@ var intervalTemplate = { to: undefined }; // Диапазоны времени когда грабители могут пойти на ограбление -var robberyIntervals = {}; +var robberyIntervals = { + Danny: [], + Rusty: [], + Linus: [], + Gang: [] +}; function tryRobBank(schedule, duration, workingHours) { // Высчитываем диапазоны, когда грабители могут пойти на ограбление From 319f5f007741f6cacb5cf1a7f211db563a0d5f11 Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 31 Oct 2016 23:14:57 +0500 Subject: [PATCH 21/35] =?UTF-8?q?=D0=93=D0=B8=D0=B1=D1=80=D0=B8=D0=B4=20?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=80=D0=BE=D0=B9=20=D0=B8=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D0=B9=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B9=20#4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/robbery.js b/robbery.js index dd59fd4..0fe5748 100644 --- a/robbery.js +++ b/robbery.js @@ -258,16 +258,12 @@ function getInterval(from, to) { } function intervalsComparator(first, second) { - if (first.from > second.from) { + if (first.from > second.from || + (first.from === second.from && first.to > second.to)) { return 1; } - if (first.from < second.from) { - return -1; - } - if (first.to > second.to) { - return 1; - } - if (first.to < second.to) { + if (first.from < second.from || + (first.from === second.from && first.to < second.to)) { return -1; } From 747d366c72b0a157da41dff74ddcaa2ce966851b Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 31 Oct 2016 23:17:33 +0500 Subject: [PATCH 22/35] =?UTF-8?q?=D0=93=D0=B8=D0=B1=D1=80=D0=B8=D0=B4=20?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=80=D0=BE=D0=B9=20=D0=B8=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D0=B9=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B9=20#5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/robbery.js b/robbery.js index 0fe5748..319bca2 100644 --- a/robbery.js +++ b/robbery.js @@ -220,11 +220,14 @@ function getBankSchedule(workingHours) { // Строит пересечение всех диапазонов времени всех троих грабителей, когда они // могут совершить ограбление и времени работы банка function getGangCrossedIntervals(bankSchedule) { - var crossedInterval = getCrossedIntervals(robberyIntervals.Danny, robberyIntervals.Rusty); - crossedInterval = getCrossedIntervals(crossedInterval, robberyIntervals.Linus); - crossedInterval = getCrossedIntervals(crossedInterval, bankSchedule); + var crossedIntervals = bankSchedule; + for (var robber in robberyIntervals) { + if (robberyIntervals.hasOwnProperty(robber)) { + crossedIntervals = getCrossedIntervals(crossedIntervals, robberyIntervals[robber]); + } + } - return crossedInterval; + return crossedIntervals; } // Находит все общие диапазоны, когда грабители могут совершить ограбление From 08fea2512de44e5f90c49a0d7857e29daafeb3f2 Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 31 Oct 2016 23:20:26 +0500 Subject: [PATCH 23/35] =?UTF-8?q?=D0=93=D0=B8=D0=B1=D1=80=D0=B8=D0=B4=20?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=80=D0=BE=D0=B9=20=D0=B8=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D0=B9=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B9=20#4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/robbery.js b/robbery.js index 319bca2..8bc097e 100644 --- a/robbery.js +++ b/robbery.js @@ -222,7 +222,8 @@ function getBankSchedule(workingHours) { function getGangCrossedIntervals(bankSchedule) { var crossedIntervals = bankSchedule; for (var robber in robberyIntervals) { - if (robberyIntervals.hasOwnProperty(robber)) { + if (robberyIntervals.hasOwnProperty(robber) && + robberyIntervals[robber] !== robberyIntervals.Gang) { crossedIntervals = getCrossedIntervals(crossedIntervals, robberyIntervals[robber]); } } From ce5f4d8784e6eba3db8b5627b4949a46aacf96f6 Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 31 Oct 2016 23:41:39 +0500 Subject: [PATCH 24/35] =?UTF-8?q?=D0=92=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D1=80=D0=B5=D0=BA=D0=BE=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=B4=D0=B0=D1=86=D0=B8=D0=B8=20v1.01?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/robbery.js b/robbery.js index 8bc097e..5a4d410 100644 --- a/robbery.js +++ b/robbery.js @@ -6,10 +6,10 @@ */ exports.isStar = false; +var DAYS_FOR_ROBBERY = 3; var BANK_TIMEZONE = 0; // временная зона банка var MINUTES_IN_HOUR = 60; var MINUTES_IN_DAY = 24 * MINUTES_IN_HOUR; -var DAYS_FOR_ROBBERY = 3; var MAX_MINUTES = DAYS_FOR_ROBBERY * MINUTES_IN_DAY - 1; // макс. 3 дня на ограбление и -1 минута var DATE_PATTERN = /(([БВНПРСТЧ]+) )?(\d+):(\d+)([+-]\d+)/i; var WEEKDAYS = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС']; @@ -88,9 +88,6 @@ var intervalTemplate = { }; // Диапазоны времени когда грабители могут пойти на ограбление var robberyIntervals = { - Danny: [], - Rusty: [], - Linus: [], Gang: [] }; @@ -111,12 +108,18 @@ function tryRobBank(schedule, duration, workingHours) { } function parseGangIntervals(schedule) { - robberyIntervals.Danny.splice(0); - robberyIntervals.Rusty.splice(0); - robberyIntervals.Linus.splice(0); - robberyIntervals.Danny = getFreeIntervals(schedule.Danny); - robberyIntervals.Rusty = getFreeIntervals(schedule.Rusty); - robberyIntervals.Linus = getFreeIntervals(schedule.Linus); + for (var robber in robberyIntervals) { + if (robberyIntervals.hasOwnProperty(robber) && + robberyIntervals[robber] !== robberyIntervals.Gang) { + robberyIntervals[robber].splice(0); + delete robberyIntervals[robber]; + } + } + for (var robber in schedule) { + if (schedule.hasOwnProperty(robber)) { + robberyIntervals[robber] = getFreeIntervals(schedule[robber]); + } + } } // Высчитываем диапазоны, когда грабитель может совершить ограбление @@ -135,6 +138,7 @@ function getFreeIntervals(schedule) { freeIntervals.push(getInterval(from, busyIntervals[i].from)); } // Если последний интервал, когда рабитель занят, не приходится на СР 23:59 + // то добавляем интервал с конца рабочего времени грабителя по СР 23:59 if (busyIntervals[busyIntervals.length - 1].to !== MAX_MINUTES) { from = busyIntervals[busyIntervals.length - 1].to; freeIntervals.push(getInterval(from, MAX_MINUTES)); From 7fc820da17a0ff1547864105d3abf58bd1aa6d28 Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 31 Oct 2016 23:48:04 +0500 Subject: [PATCH 25/35] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/robbery.js b/robbery.js index 5a4d410..dcdcfb9 100644 --- a/robbery.js +++ b/robbery.js @@ -92,6 +92,8 @@ var robberyIntervals = { }; function tryRobBank(schedule, duration, workingHours) { + // Очищаем значения от предыдущего выполнения скрипта + clearRobIntervals(); // Высчитываем диапазоны, когда грабители могут пойти на ограбление parseGangIntervals(schedule); // Составляем диапазоны времени работы банка @@ -108,6 +110,14 @@ function tryRobBank(schedule, duration, workingHours) { } function parseGangIntervals(schedule) { + for (var robber in schedule) { + if (schedule.hasOwnProperty(robber)) { + robberyIntervals[robber] = getFreeIntervals(schedule[robber]); + } + } +} + +function clearRobIntervals() { for (var robber in robberyIntervals) { if (robberyIntervals.hasOwnProperty(robber) && robberyIntervals[robber] !== robberyIntervals.Gang) { @@ -115,11 +125,7 @@ function parseGangIntervals(schedule) { delete robberyIntervals[robber]; } } - for (var robber in schedule) { - if (schedule.hasOwnProperty(robber)) { - robberyIntervals[robber] = getFreeIntervals(schedule[robber]); - } - } + robberyIntervals.Gang.splice(0); } // Высчитываем диапазоны, когда грабитель может совершить ограбление From 1842c0c89a90cdbd3976b8f8f407543543bdac62 Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 31 Oct 2016 23:56:32 +0500 Subject: [PATCH 26/35] =?UTF-8?q?=D0=92=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D1=80=D0=B5=D0=BA=D0=BE=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=B4=D0=B0=D1=86=D0=B8=D0=B8=20v1.02?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/robbery.js b/robbery.js index dcdcfb9..e41a663 100644 --- a/robbery.js +++ b/robbery.js @@ -87,13 +87,12 @@ var intervalTemplate = { to: undefined }; // Диапазоны времени когда грабители могут пойти на ограбление -var robberyIntervals = { - Gang: [] -}; +var robberyIntervals; function tryRobBank(schedule, duration, workingHours) { - // Очищаем значения от предыдущего выполнения скрипта - clearRobIntervals(); + robberyIntervals = { + Gang: [] + }; // Высчитываем диапазоны, когда грабители могут пойти на ограбление parseGangIntervals(schedule); // Составляем диапазоны времени работы банка @@ -113,6 +112,7 @@ function parseGangIntervals(schedule) { for (var robber in schedule) { if (schedule.hasOwnProperty(robber)) { robberyIntervals[robber] = getFreeIntervals(schedule[robber]); + console.log(robber + ' ' + robberyIntervals[robber]); } } } From e724d84b8437abf97beb8b34721cdae99597a906 Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 31 Oct 2016 23:58:41 +0500 Subject: [PATCH 27/35] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/robbery.js b/robbery.js index e41a663..bf93b7d 100644 --- a/robbery.js +++ b/robbery.js @@ -112,22 +112,10 @@ function parseGangIntervals(schedule) { for (var robber in schedule) { if (schedule.hasOwnProperty(robber)) { robberyIntervals[robber] = getFreeIntervals(schedule[robber]); - console.log(robber + ' ' + robberyIntervals[robber]); } } } -function clearRobIntervals() { - for (var robber in robberyIntervals) { - if (robberyIntervals.hasOwnProperty(robber) && - robberyIntervals[robber] !== robberyIntervals.Gang) { - robberyIntervals[robber].splice(0); - delete robberyIntervals[robber]; - } - } - robberyIntervals.Gang.splice(0); -} - // Высчитываем диапазоны, когда грабитель может совершить ограбление // без учёта времени работы банка function getFreeIntervals(schedule) { From 25fbcb3bd73578b3ea6a9dede65ad09a01f201e3 Mon Sep 17 00:00:00 2001 From: Alex768 Date: Tue, 1 Nov 2016 13:33:22 +0500 Subject: [PATCH 28/35] one more try --- robbery.js | 1 + 1 file changed, 1 insertion(+) diff --git a/robbery.js b/robbery.js index bf93b7d..7682376 100644 --- a/robbery.js +++ b/robbery.js @@ -111,6 +111,7 @@ function tryRobBank(schedule, duration, workingHours) { function parseGangIntervals(schedule) { for (var robber in schedule) { if (schedule.hasOwnProperty(robber)) { + robberyIntervals[robber] = []; robberyIntervals[robber] = getFreeIntervals(schedule[robber]); } } From 2211bacca6e087f20dfd716fbecaec1442cfaa3a Mon Sep 17 00:00:00 2001 From: Alex768 Date: Tue, 1 Nov 2016 13:42:44 +0500 Subject: [PATCH 29/35] one more try --- robbery.js | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/robbery.js b/robbery.js index 7682376..837c87c 100644 --- a/robbery.js +++ b/robbery.js @@ -87,12 +87,11 @@ var intervalTemplate = { to: undefined }; // Диапазоны времени когда грабители могут пойти на ограбление -var robberyIntervals; +var robberyIntervals = {}; function tryRobBank(schedule, duration, workingHours) { - robberyIntervals = { - Gang: [] - }; + // Очищаем значения от предыдущего выполнения скрипта + clearRobIntervals(); // Высчитываем диапазоны, когда грабители могут пойти на ограбление parseGangIntervals(schedule); // Составляем диапазоны времени работы банка @@ -111,18 +110,31 @@ function tryRobBank(schedule, duration, workingHours) { function parseGangIntervals(schedule) { for (var robber in schedule) { if (schedule.hasOwnProperty(robber)) { - robberyIntervals[robber] = []; robberyIntervals[robber] = getFreeIntervals(schedule[robber]); } } } +function clearRobIntervals() { + for (var robber in robberyIntervals) { + if (robberyIntervals.hasOwnProperty(robber)) { + robberyIntervals[robber].splice(0); + delete robberyIntervals[robber]; + } + } +} + // Высчитываем диапазоны, когда грабитель может совершить ограбление // без учёта времени работы банка function getFreeIntervals(schedule) { + var freeIntervals = []; + if (schedule.length === 0) { + freeIntervals.push(getInterval(0, MAX_MINUTES)); + + return freeIntervals; + } var busyIntervals = getBusyIntervals(schedule); busyIntervals.sort(intervalsComparator); - var freeIntervals = []; var from = 0; for (var i = 0; i < busyIntervals.length; i++) { // Если грабитель занят с в ПН 00:00, то интервала с ПН 00:00 до ПН 00:00 нет @@ -221,8 +233,7 @@ function getBankSchedule(workingHours) { function getGangCrossedIntervals(bankSchedule) { var crossedIntervals = bankSchedule; for (var robber in robberyIntervals) { - if (robberyIntervals.hasOwnProperty(robber) && - robberyIntervals[robber] !== robberyIntervals.Gang) { + if (robberyIntervals.hasOwnProperty(robber)) { crossedIntervals = getCrossedIntervals(crossedIntervals, robberyIntervals[robber]); } } From 87bbb9c8b2f4525feacb08773660c2c279bdc481 Mon Sep 17 00:00:00 2001 From: Alex768 Date: Tue, 1 Nov 2016 13:45:04 +0500 Subject: [PATCH 30/35] one more try --- robbery.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/robbery.js b/robbery.js index 837c87c..2be5791 100644 --- a/robbery.js +++ b/robbery.js @@ -129,12 +129,9 @@ function clearRobIntervals() { function getFreeIntervals(schedule) { var freeIntervals = []; if (schedule.length === 0) { - freeIntervals.push(getInterval(0, MAX_MINUTES)); - - return freeIntervals; + return [].push(getInterval(0, MAX_MINUTES));; } - var busyIntervals = getBusyIntervals(schedule); - busyIntervals.sort(intervalsComparator); + var busyIntervals = getBusyIntervals(schedule).sort(intervalsComparator); var from = 0; for (var i = 0; i < busyIntervals.length; i++) { // Если грабитель занят с в ПН 00:00, то интервала с ПН 00:00 до ПН 00:00 нет From 8ad5d0846ff459401ab12afd3adf41720fc4f0a1 Mon Sep 17 00:00:00 2001 From: Alex768 Date: Tue, 1 Nov 2016 13:51:33 +0500 Subject: [PATCH 31/35] one more try --- robbery.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/robbery.js b/robbery.js index 2be5791..d2f654f 100644 --- a/robbery.js +++ b/robbery.js @@ -129,9 +129,9 @@ function clearRobIntervals() { function getFreeIntervals(schedule) { var freeIntervals = []; if (schedule.length === 0) { - return [].push(getInterval(0, MAX_MINUTES));; + return [].push(getInterval(0, MAX_MINUTES)); } - var busyIntervals = getBusyIntervals(schedule).sort(intervalsComparator); + var busyIntervals = getBusyIntervals(schedule); var from = 0; for (var i = 0; i < busyIntervals.length; i++) { // Если грабитель занят с в ПН 00:00, то интервала с ПН 00:00 до ПН 00:00 нет @@ -164,7 +164,7 @@ function getBusyIntervals(schedule) { // Склеиваем пересекающиеся интервалы mergeBusyIntervals(intervals); - return intervals; + return intervals.sort(intervalsComparator); } function mergeBusyIntervals(busyIntervals) { From aee6ad96ac0c3e2261e40c9f48ff77cb66f2d9af Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 7 Nov 2016 20:15:54 +0500 Subject: [PATCH 32/35] =?UTF-8?q?=D0=9C=D0=B5=D0=BB=D0=BA=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 132 ++++++++++++++++++++--------------------------------- 1 file changed, 50 insertions(+), 82 deletions(-) diff --git a/robbery.js b/robbery.js index d2f654f..36d8139 100644 --- a/robbery.js +++ b/robbery.js @@ -6,12 +6,12 @@ */ exports.isStar = false; -var DAYS_FOR_ROBBERY = 3; var BANK_TIMEZONE = 0; // временная зона банка var MINUTES_IN_HOUR = 60; var MINUTES_IN_DAY = 24 * MINUTES_IN_HOUR; +var DAYS_FOR_ROBBERY = 3; var MAX_MINUTES = DAYS_FOR_ROBBERY * MINUTES_IN_DAY - 1; // макс. 3 дня на ограбление и -1 минута -var DATE_PATTERN = /(([БВНПРСТЧ]+) )?(\d+):(\d+)([+-]\d+)/i; +var DATE_PATTERN = /(([БВНПРСТЧ]{2})\s)?(\d{2}):(\d{2})([+-]\d{1,2})/i; var WEEKDAYS = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС']; /** @@ -75,30 +75,19 @@ function getBaseTimeZone(workingHours) { return parseInt(DATE_PATTERN.exec(workingHours.from)[5], 10); } -var robberyEventTemplate = { - ready: false, - day: undefined, - hours: undefined, - minutes: undefined -}; -// Шаблон объекта для диапазонов времени -var intervalTemplate = { - from: undefined, - to: undefined -}; // Диапазоны времени когда грабители могут пойти на ограбление -var robberyIntervals = {}; +var robberyIntervals; function tryRobBank(schedule, duration, workingHours) { - // Очищаем значения от предыдущего выполнения скрипта - clearRobIntervals(); + robberyIntervals = {}; // Высчитываем диапазоны, когда грабители могут пойти на ограбление parseGangIntervals(schedule); // Составляем диапазоны времени работы банка var bankSchedule = getBankSchedule(workingHours); // Делаем пересечение всех диапазонов свободного времени грабителей // и времени работы банка - robberyIntervals.Gang = getGangCrossedIntervals(bankSchedule); + robberyIntervals['Gang'] = getGangCrossedIntervals(bankSchedule); + console.info(robberyIntervals); // Из готовых диапазонов получаем время, когда можно ограбить банк // с учётом продолжительности ограбления (если вообще можно) var robberyTime = getRobberyTime(duration); @@ -115,23 +104,11 @@ function parseGangIntervals(schedule) { } } -function clearRobIntervals() { - for (var robber in robberyIntervals) { - if (robberyIntervals.hasOwnProperty(robber)) { - robberyIntervals[robber].splice(0); - delete robberyIntervals[robber]; - } - } -} - // Высчитываем диапазоны, когда грабитель может совершить ограбление // без учёта времени работы банка function getFreeIntervals(schedule) { - var freeIntervals = []; - if (schedule.length === 0) { - return [].push(getInterval(0, MAX_MINUTES)); - } var busyIntervals = getBusyIntervals(schedule); + var freeIntervals = []; var from = 0; for (var i = 0; i < busyIntervals.length; i++) { // Если грабитель занят с в ПН 00:00, то интервала с ПН 00:00 до ПН 00:00 нет @@ -152,36 +129,23 @@ function getFreeIntervals(schedule) { } function getBusyIntervals(schedule) { - var intervals = []; - var from = 0; - var to = 0; - for (var i = 0; i < schedule.length; i++) { - from = dateToMinutes(schedule[i].from); - to = dateToMinutes(schedule[i].to); - intervals.push(getInterval(from, to)); - } - intervals.sort(intervalsComparator); - // Склеиваем пересекающиеся интервалы - mergeBusyIntervals(intervals); + var intervals = schedule.reduce(function (accumulator, scheduleItem) { + var interval = getInterval(dateToMinutes(scheduleItem.from), + dateToMinutes(scheduleItem.to)); + for (var i = 0; i < accumulator.length; i++) { + var mergedInterval = getMergedInterval(accumulator[i], interval); + if (accumulator[i] !== mergedInterval) { + accumulator[i] = mergedInterval; + + return accumulator; + } + } + accumulator.push(interval); - return intervals.sort(intervalsComparator); -} + return accumulator; + }, []).sort(intervalsComparator); -function mergeBusyIntervals(busyIntervals) { - for (var i = 0; i < busyIntervals.length; i++) { - tryToMergeInterval(busyIntervals, i, i + 1); - } -} - -function tryToMergeInterval(busyIntervals, current, next) { - for (var i = next; i < busyIntervals.length; i++) { - var mergedInterval = getMergedInterval(busyIntervals[current], busyIntervals[i]); - if (mergedInterval !== null) { - busyIntervals[current] = mergedInterval; - busyIntervals.splice(i, 1); - i--; - } - } + return intervals; } function getMergedInterval(first, second) { @@ -211,12 +175,12 @@ function getMergedInterval(first, second) { return getInterval(from, to); } - return null; + return first; } function getBankSchedule(workingHours) { var schedule = []; - for (var day = 0; day < DAYS_FOR_ROBBERY; day++) { + for (var day = 0; day < 3; day++) { var from = dateToMinutes(WEEKDAYS[day] + ' ' + workingHours.from); var to = dateToMinutes(WEEKDAYS[day] + ' ' + workingHours.to); schedule.push(getInterval(from, to)); @@ -260,29 +224,28 @@ function crossTwoIntervals(first, second, crossedIntervals) { crossedIntervals.push(getInterval(maxFrom, minTo)); } -function getInterval(from, to) { - var interval = Object.create(intervalTemplate); - interval.from = from; - interval.to = to; - - return interval; +function getInterval(argFrom, argTo) { + return { + from: argFrom, + to: argTo + }; } function intervalsComparator(first, second) { if (first.from > second.from || - (first.from === second.from && first.to > second.to)) { + first.from === second.from && first.to > second.to) { return 1; } if (first.from < second.from || - (first.from === second.from && first.to < second.to)) { + first.from === second.from && first.to < second.to) { return -1; } return 0; } -// Считаем количество минут, прошедших с ПН 00:00+(Часовой Пояс Банка) -// Например, СР 15:00+3 -> 3900 (2880 прошло с ПН по ВТ 00:00 и 17 часов = 1020) +// Считаем количество минут, прошедших с ПН 00:00+5 +// Например, СР 15:00+3 -> 3900 (2880 прошло с ПН по СР 00:00 и 17 часов = 1020) function dateToMinutes(date) { var timeZoneOffset = BANK_TIMEZONE - Number(DATE_PATTERN.exec(date)[5]); var day = DATE_PATTERN.exec(date)[2]; @@ -304,8 +267,8 @@ function dayToMinutes(day) { // Вернёт количество минут, считая с ПН 00:00 до момента, когда можно // совершить ограбление, либо undefined function getRobberyTime(duration) { - for (var i = 0; i < robberyIntervals.Gang.length; i++) { - var interval = robberyIntervals.Gang[i]; + for (var i = 0; i < robberyIntervals['Gang'].length; i++) { + var interval = robberyIntervals['Gang'][i]; if (interval.to - interval.from >= duration) { return interval.from; } @@ -317,17 +280,22 @@ function getRobberyTime(duration) { // Преобразуем количество минут, считая с ПН 00:00 до момента, когда можно // совершить ограбление и заполняем поля объекта robberyEvent function getRobberyEvent(robberyTime) { - var robberyEvent = Object.create(robberyEventTemplate); if (robberyTime === undefined) { - return robberyEvent; + return { + ready: false + }; } - robberyEvent.ready = true; - robberyEvent.day = WEEKDAYS[Math.floor(robberyTime / MINUTES_IN_DAY)]; - robberyTime -= WEEKDAYS.indexOf(robberyEvent.day) * MINUTES_IN_DAY; - var minutes = robberyTime % MINUTES_IN_HOUR; - robberyEvent.minutes = (minutes < 10) ? '0' + minutes : minutes; - var hours = (robberyTime - minutes) / MINUTES_IN_HOUR; - robberyEvent.hours = (hours < 10) ? '0' + hours : hours; + var eventDay = WEEKDAYS[Math.floor(robberyTime / MINUTES_IN_DAY)]; + robberyTime -= WEEKDAYS.indexOf(eventDay) * MINUTES_IN_DAY; + var eventMinutes = robberyTime % MINUTES_IN_HOUR; + eventMinutes = (eventMinutes < 10) ? '0' + eventMinutes : eventMinutes; + var eventHours = (robberyTime - eventMinutes) / MINUTES_IN_HOUR; + eventHours = (eventHours < 10) ? '0' + eventHours : eventHours; - return robberyEvent; + return { + ready: true, + day: eventDay, + hours: eventHours, + minutes: eventMinutes + }; } From 9cc39ae0310d9e43336817f64bc3c127b1cfb27c Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 7 Nov 2016 20:19:44 +0500 Subject: [PATCH 33/35] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/robbery.js b/robbery.js index 36d8139..9fe20c5 100644 --- a/robbery.js +++ b/robbery.js @@ -86,7 +86,7 @@ function tryRobBank(schedule, duration, workingHours) { var bankSchedule = getBankSchedule(workingHours); // Делаем пересечение всех диапазонов свободного времени грабителей // и времени работы банка - robberyIntervals['Gang'] = getGangCrossedIntervals(bankSchedule); + robberyIntervals.Gang = getGangCrossedIntervals(bankSchedule); console.info(robberyIntervals); // Из готовых диапазонов получаем время, когда можно ограбить банк // с учётом продолжительности ограбления (если вообще можно) @@ -267,8 +267,8 @@ function dayToMinutes(day) { // Вернёт количество минут, считая с ПН 00:00 до момента, когда можно // совершить ограбление, либо undefined function getRobberyTime(duration) { - for (var i = 0; i < robberyIntervals['Gang'].length; i++) { - var interval = robberyIntervals['Gang'][i]; + for (var i = 0; i < robberyIntervals.Gang.length; i++) { + var interval = robberyIntervals.Gang[i]; if (interval.to - interval.from >= duration) { return interval.from; } From 17b3272dc589933c6b0f512329aa551742f11949 Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 7 Nov 2016 23:02:16 +0500 Subject: [PATCH 34/35] =?UTF-8?q?=D0=9C=D0=B5=D0=BB=D0=BA=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 56 +++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/robbery.js b/robbery.js index 9fe20c5..a38083a 100644 --- a/robbery.js +++ b/robbery.js @@ -7,6 +7,7 @@ exports.isStar = false; var BANK_TIMEZONE = 0; // временная зона банка +var ROBBERY_DURATION = 0; var MINUTES_IN_HOUR = 60; var MINUTES_IN_DAY = 24 * MINUTES_IN_HOUR; var DAYS_FOR_ROBBERY = 3; @@ -25,7 +26,8 @@ var WEEKDAYS = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС']; exports.getAppropriateMoment = function (schedule, duration, workingHours) { BANK_TIMEZONE = getBaseTimeZone(workingHours); console.info(schedule, duration, workingHours); - var robberyEvent = tryRobBank(schedule, duration, workingHours); + ROBBERY_DURATION = duration; + var robberyEvent = getRobberyEvent(schedule, workingHours); return { @@ -75,28 +77,25 @@ function getBaseTimeZone(workingHours) { return parseInt(DATE_PATTERN.exec(workingHours.from)[5], 10); } -// Диапазоны времени когда грабители могут пойти на ограбление -var robberyIntervals; - -function tryRobBank(schedule, duration, workingHours) { - robberyIntervals = {}; +function getRobberyEvent(schedule, workingHours) { + // Диапазоны времени когда грабители могут пойти на ограбление + var robberyIntervals = {}; // Высчитываем диапазоны, когда грабители могут пойти на ограбление - parseGangIntervals(schedule); + parseGangIntervals(robberyIntervals, schedule); // Составляем диапазоны времени работы банка var bankSchedule = getBankSchedule(workingHours); // Делаем пересечение всех диапазонов свободного времени грабителей // и времени работы банка - robberyIntervals.Gang = getGangCrossedIntervals(bankSchedule); - console.info(robberyIntervals); + robberyIntervals.Gang = getRobberyIntervals(robberyIntervals, bankSchedule); // Из готовых диапазонов получаем время, когда можно ограбить банк // с учётом продолжительности ограбления (если вообще можно) - var robberyTime = getRobberyTime(duration); - var robberyEvent = getRobberyEvent(robberyTime); + var robberyTime = getRobberyTime(robberyIntervals); + var robberyEvent = findRobberyEvent(robberyTime); return robberyEvent; } -function parseGangIntervals(schedule) { +function parseGangIntervals(robberyIntervals, schedule) { for (var robber in schedule) { if (schedule.hasOwnProperty(robber)) { robberyIntervals[robber] = getFreeIntervals(schedule[robber]); @@ -107,6 +106,12 @@ function parseGangIntervals(schedule) { // Высчитываем диапазоны, когда грабитель может совершить ограбление // без учёта времени работы банка function getFreeIntervals(schedule) { + var freeIntervals = []; + if (schedule.length === 0) { + freeIntervals.push(getInterval(0, MAX_MINUTES)); + + return freeIntervals; + } var busyIntervals = getBusyIntervals(schedule); var freeIntervals = []; var from = 0; @@ -191,15 +196,15 @@ function getBankSchedule(workingHours) { // Строит пересечение всех диапазонов времени всех троих грабителей, когда они // могут совершить ограбление и времени работы банка -function getGangCrossedIntervals(bankSchedule) { - var crossedIntervals = bankSchedule; +function getRobberyIntervals(robberyIntervals, bankSchedule) { + var intervals = bankSchedule; for (var robber in robberyIntervals) { if (robberyIntervals.hasOwnProperty(robber)) { - crossedIntervals = getCrossedIntervals(crossedIntervals, robberyIntervals[robber]); + intervals = getCrossedIntervals(intervals, robberyIntervals[robber]); } } - return crossedIntervals; + return intervals; } // Находит все общие диапазоны, когда грабители могут совершить ограбление @@ -266,20 +271,19 @@ function dayToMinutes(day) { // Вернёт количество минут, считая с ПН 00:00 до момента, когда можно // совершить ограбление, либо undefined -function getRobberyTime(duration) { - for (var i = 0; i < robberyIntervals.Gang.length; i++) { - var interval = robberyIntervals.Gang[i]; - if (interval.to - interval.from >= duration) { - return interval.from; - } - } +function getRobberyTime(robberyIntervals) { + var filtered = robberyIntervals.Gang.filter(filterIntervals); + + return (filtered.length > 0) ? filtered[0].from : undefined; +} - return undefined; +function filterIntervals(interval) { + return interval.to - interval.from >= ROBBERY_DURATION; } // Преобразуем количество минут, считая с ПН 00:00 до момента, когда можно -// совершить ограбление и заполняем поля объекта robberyEvent -function getRobberyEvent(robberyTime) { +// совершить ограбление +function findRobberyEvent(robberyTime) { if (robberyTime === undefined) { return { ready: false From 1def2f32d636dc7ee1f3c10a7e94c419f47b6ce3 Mon Sep 17 00:00:00 2001 From: Alex768 Date: Mon, 7 Nov 2016 23:05:09 +0500 Subject: [PATCH 35/35] =?UTF-8?q?=D0=9C=D0=B5=D0=BB=D0=BA=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robbery.js | 1 - 1 file changed, 1 deletion(-) diff --git a/robbery.js b/robbery.js index a38083a..41c57b7 100644 --- a/robbery.js +++ b/robbery.js @@ -113,7 +113,6 @@ function getFreeIntervals(schedule) { return freeIntervals; } var busyIntervals = getBusyIntervals(schedule); - var freeIntervals = []; var from = 0; for (var i = 0; i < busyIntervals.length; i++) { // Если грабитель занят с в ПН 00:00, то интервала с ПН 00:00 до ПН 00:00 нет