Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 127 additions & 3 deletions robbery.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,80 @@
*/
exports.isStar = true;

var DAYS = [
'ПН', 'ВТ', 'СР', 'ЧТ',
'ПТ', 'СБ', 'ВС'
];
var THIRTY_MINUTES = 1800;

function dateToTimestamp(str) {
for (var i = 0; i < DAYS.length; i++) {
str = str.replace(DAYS[i], i + 1);
}
str = str.replace(/(\d) (\d{2}:\d{2})(\+\d+)?/, '1 $1 1970 $2 GMT$3');

return Date.parse(str) / 1000;
}

function toTimestampInterval(interval) {
return {
'from': dateToTimestamp(interval.from),
'to': dateToTimestamp(interval.to)
};
}

function normalizeSchedule(schedule) {
var busyIntervals = [];
Object.keys(schedule).forEach(function (thug) {
var busy = schedule[thug].map(toTimestampInterval);
busyIntervals = busyIntervals.concat(busy);
});
busyIntervals = busyIntervals.sort(function (one, another) {
if (one.from < another.from) {
return -1;
}
if (one.from > another.from) {
return 1;
}

return 0;
});

return busyIntervals;
}

function getWorkingDays(workingHours) {
var workingDays = [];
for (var i = 0; i < 3; i++) {
var from = DAYS[i] + ' ' + workingHours.from;
var to = DAYS[i] + ' ' + workingHours.to;
workingDays.push({
'from': dateToTimestamp(from),
'to': dateToTimestamp(to)
});
}

return workingDays;
}

function getSpareTimes(schedule, weekStart, deadline) {
var spareTime = [];
var current = weekStart;
for (var i = 0; i < schedule.length; i++) {
if (current >= schedule[i].from) {
current = current < schedule[i].to ? schedule[i].to : current;
continue;
}
spareTime.push({ 'from': current, 'to': schedule[i].from });
current = schedule[i].to;
}
if (current < deadline) {
spareTime.push({ 'from': current, 'to': deadline });
}

return spareTime;
}

/**
* @param {Object} schedule – Расписание Банды
* @param {Number} duration - Время на ограбление в минутах
Expand All @@ -15,7 +89,26 @@ exports.isStar = true;
* @returns {Object}
*/
exports.getAppropriateMoment = function (schedule, duration, workingHours) {
console.info(schedule, duration, workingHours);
schedule = normalizeSchedule(schedule);
duration *= 60;
var workingDays = getWorkingDays(workingHours);
var bankTimezone = parseInt(/\+(\d+)$/.exec(workingHours.from)[1]);
var weekStart = Date.parse('1 1 1970 00:00 GMT+' + bankTimezone) / 1000;
var deadline = Date.parse('1 3 1970 23:59 GMT+' + bankTimezone) / 1000;
var spareTime = getSpareTimes(schedule, weekStart, deadline);

var robberyTime = [];
workingDays.forEach(function (workingDay) {
var possible = [];
for (var j = 0; j < spareTime.length; j++) {
var minTo = Math.min(workingDay.to, spareTime[j].to);
var maxFrom = Math.max(workingDay.from, spareTime[j].from);
if (minTo - maxFrom >= duration) {
possible.push({ 'from': maxFrom, 'to': minTo });
}
}
robberyTime = robberyTime.concat(possible);
});

return {

Expand All @@ -24,7 +117,7 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) {
* @returns {Boolean}
*/
exists: function () {
return false;
return robberyTime.length > 0;
},

/**
Expand All @@ -35,7 +128,23 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) {
* @returns {String}
*/
format: function (template) {
return template;
if (robberyTime.length === 0) {
return '';
}
var date = new Date();
date.setTime((robberyTime[0].from + bankTimezone * 3600) * 1000);

var minutes = date
.getUTCMinutes()
.toLocaleString(undefined, { 'minimumIntegerDigits': 2 });
var hours = date
.getUTCHours()
.toLocaleString(undefined, { 'minimumIntegerDigits': 2 });

return template
.replace('%HH', hours)
.replace('%MM', minutes)
.replace('%DD', DAYS[date.getUTCDate() - 1]);
},

/**
Expand All @@ -44,6 +153,21 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) {
* @returns {Boolean}
*/
tryLater: function () {
if (!this.exists()) {
return false;
}

if (robberyTime[0].to - robberyTime[0].from - THIRTY_MINUTES >= duration) {
robberyTime[0].from = robberyTime[0].from + THIRTY_MINUTES;

return true;
}
if (robberyTime.length > 1) {
robberyTime.shift();

return true;
}

return false;
}
};
Expand Down