-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Филиппович Алексей #53
base: master
Are you sure you want to change the base?
Changes from all commits
bb0bbc3
e24fda2
48e35ff
f3c5246
88b4a8e
2610482
91f4e53
90caf24
2a524fb
1f781f8
b30bb59
a5aa85f
a712e5a
70b0eb0
eb6e46c
083ea98
2710c6d
efc10b6
cab1115
6027818
319f5f0
747d366
08fea25
ce5f4d8
7fc820d
1842c0c
e724d84
25fbcb3
2211bac
87bbb9c
8ad5d08
aee6ad9
9cc39ae
17b3272
1def2f3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,16 @@ | |
* Сделано задание на звездочку | ||
* Реализовано оба метода и tryLater | ||
*/ | ||
exports.isStar = true; | ||
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; | ||
var MAX_MINUTES = DAYS_FOR_ROBBERY * MINUTES_IN_DAY - 1; // макс. 3 дня на ограбление и -1 минута | ||
var DATE_PATTERN = /(([БВНПРСТЧ]{2})\s)?(\d{2}):(\d{2})([+-]\d{1,2})/i; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. сам составил? |
||
var WEEKDAYS = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС']; | ||
|
||
/** | ||
* @param {Object} schedule – Расписание Банды | ||
|
@@ -15,16 +24,24 @@ exports.isStar = true; | |
* @returns {Object} | ||
*/ | ||
exports.getAppropriateMoment = function (schedule, duration, workingHours) { | ||
BANK_TIMEZONE = getBaseTimeZone(workingHours); | ||
console.info(schedule, duration, workingHours); | ||
ROBBERY_DURATION = duration; | ||
var robberyEvent = getRobberyEvent(schedule, workingHours); | ||
|
||
return { | ||
|
||
ready: robberyEvent.ready, | ||
day: robberyEvent.day, | ||
hours: robberyEvent.hours, | ||
minutes: robberyEvent.minutes, | ||
|
||
/** | ||
* Найдено ли время | ||
* @returns {Boolean} | ||
*/ | ||
exists: function () { | ||
return false; | ||
return this.ready; | ||
}, | ||
|
||
/** | ||
|
@@ -35,7 +52,14 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) { | |
* @returns {String} | ||
*/ | ||
format: function (template) { | ||
return template; | ||
if (!this.ready) { | ||
return ''; | ||
} | ||
|
||
return template | ||
.replace('%DD', this.day) | ||
.replace('%HH', this.hours) | ||
.replace('%MM', this.minutes); | ||
}, | ||
|
||
/** | ||
|
@@ -48,3 +72,233 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) { | |
} | ||
}; | ||
}; | ||
|
||
function getBaseTimeZone(workingHours) { | ||
return parseInt(DATE_PATTERN.exec(workingHours.from)[5], 10); | ||
} | ||
|
||
function getRobberyEvent(schedule, workingHours) { | ||
// Диапазоны времени когда грабители могут пойти на ограбление | ||
var robberyIntervals = {}; | ||
// Высчитываем диапазоны, когда грабители могут пойти на ограбление | ||
parseGangIntervals(robberyIntervals, schedule); | ||
// Составляем диапазоны времени работы банка | ||
var bankSchedule = getBankSchedule(workingHours); | ||
// Делаем пересечение всех диапазонов свободного времени грабителей | ||
// и времени работы банка | ||
robberyIntervals.Gang = getRobberyIntervals(robberyIntervals, bankSchedule); | ||
// Из готовых диапазонов получаем время, когда можно ограбить банк | ||
// с учётом продолжительности ограбления (если вообще можно) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. за комментарии от души спасибо 👍 |
||
var robberyTime = getRobberyTime(robberyIntervals); | ||
var robberyEvent = findRobberyEvent(robberyTime); | ||
|
||
return robberyEvent; | ||
} | ||
|
||
function parseGangIntervals(robberyIntervals, schedule) { | ||
for (var robber in schedule) { | ||
if (schedule.hasOwnProperty(robber)) { | ||
robberyIntervals[robber] = getFreeIntervals(schedule[robber]); | ||
} | ||
} | ||
} | ||
|
||
// Высчитываем диапазоны, когда грабитель может совершить ограбление | ||
// без учёта времени работы банка | ||
function getFreeIntervals(schedule) { | ||
var freeIntervals = []; | ||
if (schedule.length === 0) { | ||
freeIntervals.push(getInterval(0, MAX_MINUTES)); | ||
|
||
return freeIntervals; | ||
} | ||
var busyIntervals = getBusyIntervals(schedule); | ||
var from = 0; | ||
for (var i = 0; i < busyIntervals.length; i++) { | ||
// Если грабитель занят с в ПН 00:00, то интервала с ПН 00:00 до ПН 00:00 нет | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. вообще непонятный комментарий. Он совсем запутывает. И на самом деле вот это сомнительное место |
||
if (i === 0 && busyIntervals[i].from === 0) { | ||
continue; | ||
} | ||
from = (i === 0) ? 0 : busyIntervals[i - 1].to; | ||
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)); | ||
} | ||
|
||
return freeIntervals; | ||
} | ||
|
||
function getBusyIntervals(schedule) { | ||
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 accumulator; | ||
}, []).sort(intervalsComparator); | ||
|
||
return intervals; | ||
} | ||
|
||
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 first; | ||
} | ||
|
||
function getBankSchedule(workingHours) { | ||
var schedule = []; | ||
for (var day = 0; day < 3; day++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 3 в константу |
||
var from = dateToMinutes(WEEKDAYS[day] + ' ' + workingHours.from); | ||
var to = dateToMinutes(WEEKDAYS[day] + ' ' + workingHours.to); | ||
schedule.push(getInterval(from, to)); | ||
} | ||
|
||
return schedule; | ||
} | ||
|
||
// Строит пересечение всех диапазонов времени всех троих грабителей, когда они | ||
// могут совершить ограбление и времени работы банка | ||
function getRobberyIntervals(robberyIntervals, bankSchedule) { | ||
var intervals = bankSchedule; | ||
for (var robber in robberyIntervals) { | ||
if (robberyIntervals.hasOwnProperty(robber)) { | ||
intervals = getCrossedIntervals(intervals, robberyIntervals[robber]); | ||
} | ||
} | ||
|
||
return intervals; | ||
} | ||
|
||
// Находит все общие диапазоны, когда грабители могут совершить ограбление | ||
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 crossedIntervals; | ||
} | ||
|
||
// Находим пересечение двух диапазонов времени | ||
function crossTwoIntervals(first, second, crossedIntervals) { | ||
if (first.from > second.to || first.to < second.from) { | ||
return; | ||
} | ||
var maxFrom = Math.max(first.from, second.from); | ||
var minTo = Math.min(first.to, second.to); | ||
crossedIntervals.push(getInterval(maxFrom, minTo)); | ||
} | ||
|
||
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) { | ||
return 1; | ||
} | ||
if (first.from < second.from || | ||
first.from === second.from && first.to < second.to) { | ||
return -1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
// Считаем количество минут, прошедших с ПН 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]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. вынеси DATE_PATTERN.exec(date) в переменную, незачем делать это каждый раз |
||
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) { | ||
if (WEEKDAYS.indexOf(day) !== -1) { | ||
return WEEKDAYS.indexOf(day) * MINUTES_IN_DAY; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
// Вернёт количество минут, считая с ПН 00:00 до момента, когда можно | ||
// совершить ограбление, либо undefined | ||
function getRobberyTime(robberyIntervals) { | ||
var filtered = robberyIntervals.Gang.filter(filterIntervals); | ||
|
||
return (filtered.length > 0) ? filtered[0].from : undefined; | ||
} | ||
|
||
function filterIntervals(interval) { | ||
return interval.to - interval.from >= ROBBERY_DURATION; | ||
} | ||
|
||
// Преобразуем количество минут, считая с ПН 00:00 до момента, когда можно | ||
// совершить ограбление | ||
function findRobberyEvent(robberyTime) { | ||
if (robberyTime === undefined) { | ||
return { | ||
ready: false | ||
}; | ||
} | ||
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 { | ||
ready: true, | ||
day: eventDay, | ||
hours: eventHours, | ||
minutes: eventMinutes | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
переменные нао определять максимально близко к тому месту, где они потом используются