Skip to content
179 changes: 176 additions & 3 deletions robbery.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,156 @@
*/
exports.isStar = true;

var DAYS_INDEXES = { 'ПН': 0, 'ВТ': 1, 'СР': 2, 'ЧТ': 3, 'ПТ': 4, 'СБ': 5, 'ВС': 6 };
var DAYS_NAMES = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС'];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Почему удалил доки?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

мешает

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Но они же несут полезную информацию!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это ключи предыдущего объекта

var MINUTES_IN_HOUR = 60;
var HOURS_IN_DAY = 24;
var MINUTES_IN_DAY = HOURS_IN_DAY * MINUTES_IN_HOUR;
var MINUTES_TO_START_LATER = 30;
var DAYS_TO_HACK = 3;


function TimeInterval(start, end) {
this.start = start;
this.end = end;

this.getLength = function () {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

start и end известны на этапе создания объекта, почему length нужно вычислять, а нельзя сделать полем?

return this.end - this.start;
};

this.getNextDay = function () {
return new TimeInterval(this.start + MINUTES_IN_DAY, this.end + MINUTES_IN_DAY);
};

this.isTimeInInterval = function (time) {
return this.start <= time && time <= this.end;
};
}

function isTimeInIntervals(timeIntervalsArray, time) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Название читаю, а понять что она делает не могу

for (var i = 0; i < timeIntervalsArray.length; i++) {
if (timeIntervalsArray[i].isTimeInInterval(time)) {
return true;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а зачем тут отступ перед return?)

}
}

return false;
}

function strDateToDateObj(strDate) {
var strDateCopy = strDate.slice();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Зачем это нужно?

if (DAYS_INDEXES[strDateCopy.slice(0, 2)] === undefined) {
strDateCopy = 'ПН ' + strDateCopy;
}
var dateInfo = {
day: DAYS_INDEXES[strDateCopy.slice(0, 2)],
hours: parseInt(strDateCopy.slice(3, 5), 10),
minutes: parseInt(strDateCopy.slice(6, 8), 10),
timezone: parseInt(strDateCopy.slice(9, strDateCopy.length), 10)
};
dateInfo.intValue = dateInfo.day * MINUTES_IN_DAY +
(dateInfo.hours - dateInfo.timezone) * MINUTES_IN_HOUR + dateInfo.minutes;

return dateInfo;
}

function getGangsterNames(schedule) {
var gangsterNames = [];
for (var gangsterName in schedule) {
if (schedule.hasOwnProperty(gangsterName)) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Попробуй написать это как-то по-другому. Попроще :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ну если честно я не знаю как. https://learn.javascript.ru/object-for-in смотрел тут. hasOwnProperty для lint'a

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gangsterNames.push(gangsterName);
}
}

return gangsterNames;
}

function createTimeIntervalWithShift(time, shift) {
return new TimeInterval(strDateToDateObj(time.from).intValue + shift,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это нечитаемый однострочник, нужно вынести аргументы TimeIntreval в читаемые переменные

strDateToDateObj(time.to).intValue + shift);
}

function simplifyTimesIntervals(timeIntervals, duration) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Название функции переводится как «Упростить временные интервалы». Я честно не понимаю что тут подразумевается

var newTimeIntervals = [];
timeIntervals.forEach(function (timeInterval) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Для фильтрации массивов придумали специальную функцию https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

if (timeInterval.getLength() >= duration) {
newTimeIntervals.push(timeInterval);
}
});

return newTimeIntervals;
}

function addOrChangeLastTimeInterval(arrayIntervals, timeToStartNewInterval) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Из названия функции абсолютно не понятно что она делает. И по коду я тоже ничего не понял

var arrayLen = arrayIntervals.length;
if (arrayLen === 0 || arrayIntervals[arrayLen - 1].end !== timeToStartNewInterval - 1) {
arrayIntervals.push(new TimeInterval(timeToStartNewInterval, timeToStartNewInterval));
} else {
arrayIntervals[arrayLen - 1].end += 1;
}
}

function isGangstersNotBusy(schedule, gangsterNames, time) {
var gangstersIsNotBusy = true;
gangsterNames.forEach(function (gangster) {
if (isTimeInIntervals(schedule[gangster], time)) {
gangstersIsNotBusy = false;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно написать здесь return false;, а в конце функции -- return true;. Тогда без этой переменной обойдемся и меньше бегать по циклу будем)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

К сожалению из forEach нельзя ничего возвращать(

}
});

return gangstersIsNotBusy;
}

function getGoodTimeIntervals(schedule, gangsterNames) {
var goodTimesIntervals = [];

for (var i = 0; i < DAYS_TO_HACK * MINUTES_IN_DAY; i++) {
if (!isTimeInIntervals(schedule.Bank, i)) {
continue;
}
if (isGangstersNotBusy(schedule, gangsterNames, i)) {
addOrChangeLastTimeInterval(goodTimesIntervals, i);
}
}

return goodTimesIntervals;
}

function createGangsterScheduleWithTimeIntervals(schedule, gangsterNames, bankShift) {
var newSchedule = {};

gangsterNames.forEach(function (gangsterName) {
newSchedule[gangsterName] = [];
schedule[gangsterName].forEach(function (time) {
var intervalWithShift = createTimeIntervalWithShift(time, bankShift);
intervalWithShift.start++;
intervalWithShift.end--;
newSchedule[gangsterName].push(intervalWithShift);
});
});

return newSchedule;
}

function addToScheduleBankTimeIntervals(schedule, bankWorkingHours, bankShift) {
schedule.Bank = [createTimeIntervalWithShift(bankWorkingHours, bankShift)];
for (var dayIndex = 0; dayIndex < DAYS_TO_HACK - 1; dayIndex++) {
schedule.Bank.push(schedule.Bank[schedule.Bank.length - 1].getNextDay());
}
}

function createScheduleWithTimeIntervals(bankWorkingHours, schedule, gangsterNames) {
var bankShift = strDateToDateObj(bankWorkingHours.from).timezone * MINUTES_IN_HOUR;
var newSchedule = createGangsterScheduleWithTimeIntervals(schedule, gangsterNames, bankShift);
addToScheduleBankTimeIntervals(newSchedule, bankWorkingHours, bankShift);

return newSchedule;
}

function timeToString(time) {
return time < 10 ? '0' + time.toString() : time.toString();
}

/**
* @param {Object} schedule – Расписание Банды
* @param {Number} duration - Время на ограбление в минутах
Expand All @@ -15,7 +165,10 @@ exports.isStar = true;
* @returns {Object}
*/
exports.getAppropriateMoment = function (schedule, duration, workingHours) {
console.info(schedule, duration, workingHours);
var gangsterNames = getGangsterNames(schedule);
var newSchedule = createScheduleWithTimeIntervals(workingHours, schedule, gangsterNames);
var goodTimesIntervals = getGoodTimeIntervals(newSchedule, gangsterNames);
var goodTimesIntervalsWithGoodDuration = simplifyTimesIntervals(goodTimesIntervals, duration);

return {

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

/**
Expand All @@ -35,7 +188,17 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) {
* @returns {String}
*/
format: function (template) {
return template;
if (!this.exists()) {
return '';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Кажется, тут лишний перенос строки

}

var startInterval = goodTimesIntervalsWithGoodDuration[0];
var day = parseInt(startInterval.start / (MINUTES_IN_DAY), 10);
var hour = parseInt(startInterval.start / MINUTES_IN_HOUR, 10) - day * HOURS_IN_DAY;
var minutes = startInterval.start % MINUTES_IN_HOUR;

return template.replace('%DD', DAYS_NAMES[day]).replace('%HH', timeToString(hour))
.replace('%MM', timeToString(minutes));
},

/**
Expand All @@ -44,6 +207,16 @@ exports.getAppropriateMoment = function (schedule, duration, workingHours) {
* @returns {Boolean}
*/
tryLater: function () {
var startInterval = goodTimesIntervalsWithGoodDuration[0];
if (this.exists() && (goodTimesIntervalsWithGoodDuration.length > 1 ||
startInterval.getLength() >= duration + MINUTES_TO_START_LATER)) {
startInterval.start += MINUTES_TO_START_LATER;
goodTimesIntervalsWithGoodDuration = simplifyTimesIntervals(
goodTimesIntervalsWithGoodDuration, duration);

return true;
}

return false;
}
};
Expand Down