Skip to content
226 changes: 222 additions & 4 deletions robbery.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Сделано задание на звездочку
* Реализовано оба метода и tryLater
*/
exports.isStar = true;
exports.isStar = false;

/**
* @param {Object} schedule – Расписание Банды
Expand All @@ -14,8 +14,147 @@ exports.isStar = true;
* @param {String} workingHours.to – Время закрытия, например, "18:00+5"
* @returns {Object}
*/
var DAYS_FOR_ROBBERY = ['ПН', 'ВТ', 'СР'];
var MINUTES_IN_HOUR = 60;
var resArrayIsAlreadyCreated = false;
var resultIndex = 0;
var whenBusyFrom = [];
var whenBusyTo = [];
var whenGangIsCan = [];
var incorrectData = false;

exports.getAppropriateMoment = function (schedule, duration, workingHours) {
console.info(schedule, duration, workingHours);
var bankFrom = hoursToMinutes(workingHours.from);
var bankTo = hoursToMinutes(workingHours.to);
var result = [];


function isFreeToday(name, day) {
var isBusy = false;
for (var i = 0; i < schedule[name].length; i++) {
var robberyFrom = convertToTimezone(schedule[name][i].from, workingHours);
var robberyTo = convertToTimezone(schedule[name][i].to, workingHours);
if (robberyFrom.indexOf(day) !== -1 && robberyTo.indexOf(day) !== -1) {
isBusy = checkBusyAllBankHours(hoursToMinutes(robberyFrom),
hoursToMinutes(robberyTo));

checkIntervalAndPush(hoursToMinutes(robberyFrom), hoursToMinutes(robberyTo));
} else if (robberyFrom.indexOf(day) !== -1) {
isBusy = checkBusyAllBankHours(
hoursToMinutes(robberyFrom),
hoursToMinutes('23:59+5')
);

checkIntervalAndPush(hoursToMinutes(robberyFrom), bankTo);
} else if (robberyTo.indexOf(day) !== -1) {
isBusy = checkBusyAllBankHours(hoursToMinutes('00:00+5'),
hoursToMinutes(robberyTo));

checkIntervalAndPush(bankFrom, hoursToMinutes(robberyTo));
}
if (isBusy) {
return false;
}
}

return true;
}

function checkIntervalAndPush(from, to) {
if (from <= bankTo && from >= bankFrom && to <= bankTo) {
whenBusyFrom.push(from);
whenBusyTo.push(to);
}
}

function checkBusyAllBankHours(robFrom, robTo) {
if (robFrom <= bankFrom && robTo >= bankTo) {
return true;
}

return false;
}

function searchMiddleCases(i) {
var maxTo;
if (whenBusyTo[i] < whenBusyFrom[i + 1]) {
whenGangIsCan.push(
{ fromInMins: whenBusyTo[i],
toInMins: whenBusyFrom[i + 1] });
} else {
var nextTo;
while (whenBusyTo[i] > whenBusyFrom[i + 1]) {
maxTo = whenBusyTo[i + 1];
i++;
}
if (whenBusyTo[i + 1] !== undefined) {
nextTo = whenBusyTo[i + 1];
whenGangIsCan.push({ fromInMins: maxTo, toInMins: nextTo });
}

}
}

function findWhenGangIsFree() {
whenBusyFrom.sort(function (a, b) {
return a - b;
});
whenBusyTo.sort(function (a, b) {
return a - b;
});

if (whenBusyFrom[0] > bankFrom) {
whenGangIsCan.push({ fromInMins: bankFrom, toInMins: whenBusyFrom[0] });
}
for (var i = 0; i < whenBusyFrom.length; i++) {
searchMiddleCases(i);
}
if (whenBusyTo[whenBusyTo.length - 1] < bankTo) {
whenGangIsCan.push({
fromInMins: whenBusyTo[whenBusyTo.length - 1],
toInMins: bankTo });
}
}

function uniqueVal(value, index, self) {
return self.indexOf(value) === index &&
self.indexOf(value) === index;
}

function willRobThisDay(index) {
for (var i = 0; i < whenGangIsCan.length; i++) {
if ((whenGangIsCan[i].toInMins - whenGangIsCan[i].fromInMins) >= duration) {
result.push({
resFrom: whenGangIsCan[i].fromInMins,
resTo: whenGangIsCan[i].toInMins,
day: DAYS_FOR_ROBBERY[index]
});
}
}

result.filter(uniqueVal);

whenBusyFrom = [];
whenBusyTo = [];
whenGangIsCan = [];

if (result.length !== 0) {
return true;
}

return false;
}

function gangIsFree(i) {
var allIsFree = true;
for (var robber in schedule) {
if ({}.hasOwnProperty.call(schedule, robber)) {
allIsFree = gangIsFree && isFreeToday(robber, DAYS_FOR_ROBBERY[i]);
}
}

return allIsFree;
}

return {

Expand All @@ -24,7 +163,25 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) {
* @returns {Boolean}
*/
exists: function () {
return false;
var willRob = false;
var isFree;
for (var i = 0; i < DAYS_FOR_ROBBERY.length; i++) {
isFree = gangIsFree(i);
if (isFree) {
findWhenGangIsFree();
}
if (willRobThisDay(i, resArrayIsAlreadyCreated)) {
willRob = true;
}
}
if (willRob) {
resArrayIsAlreadyCreated = true;
}
if (incorrectData) {
return false;
}

return willRob;
},

/**
Expand All @@ -35,7 +192,15 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) {
* @returns {String}
*/
format: function (template) {
return template;
if (!this.exists()) {
return '';
}
var timeArray = minutesToHours(result[resultIndex].resFrom);

return template.replace('%HH', timeArray[0])
.replace('%MM', timeArray[1])
.replace('%DD', result[resultIndex].day);

},

/**
Expand All @@ -44,7 +209,60 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) {
* @returns {Boolean}
*/
tryLater: function () {

return false;
}
};
};

function hoursToMinutes(str) {
var timeArray = str.match(/\d{1,2}/g);
if (str.indexOf('+') === -1) {
incorrectData = true;
}

return timeArray[0] * MINUTES_IN_HOUR + Number(timeArray[1]);
}

function minutesToHours(inputMinutes) {
var hours = parseInt(inputMinutes / MINUTES_IN_HOUR);
var minutes = inputMinutes % MINUTES_IN_HOUR;
if (minutes < 10) {
minutes += '0';
}
if (hours < 10) {
hours += '0';
}

return [hours, minutes];
}

function checkCorrectDay(day) {
if (day.indexOf(DAYS_FOR_ROBBERY[0]) === -1 && day.indexOf(DAYS_FOR_ROBBERY[1]) === -1 &&
day.indexOf(DAYS_FOR_ROBBERY[2]) === -1) {
incorrectData = true;
}
}

function convertToTimezone(str, workingHours) {
var bankTimezone = workingHours.from.search(/\+\d{1,2}/);
var timeArray = str.match(/\d{1,2}/g);
var dayOfWeek = str.match(/[А-Я]{2}/g);
checkCorrectDay(dayOfWeek[0]);
if (str.indexOf('+') === -1 || timeArray[2] > 23) {
incorrectData = true;
}
var deltaTimezone = Math.abs(parseInt(bankTimezone - timeArray[2]));
var newHours;
if (timeArray[2] < bankTimezone) {
newHours = Number(timeArray[0]) + deltaTimezone;

return dayOfWeek[0] + ' ' + newHours + ':' + timeArray[1] + '+' + bankTimezone;
} else if (timeArray[2] > bankTimezone) {
newHours = Number(timeArray[0]) - deltaTimezone;

return dayOfWeek[0] + ' ' + newHours + ':' + timeArray[1] + '+' + bankTimezone;
}

return str;
}