Skip to content

Макаров Виталий #11

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

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
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
305 changes: 273 additions & 32 deletions robbery.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,291 @@
'use strict';

/**
* Сделано задание на звездочку
* Реализовано оба метода и tryLater
*/
exports.isStar = true;

/**
* @param {Object} schedule – Расписание Банды
* @param {Number} duration - Время на ограбление в минутах
* @param {Object} workingHours – Время работы банка
* @param {String} workingHours.from – Время открытия, например, "10:00+5"
* @param {String} workingHours.to – Время закрытия, например, "18:00+5"
* @returns {Object}
*/
var TIME_ZONE;

exports.getAppropriateMoment = function (schedule, duration, workingHours) {
console.info(schedule, duration, workingHours);
var index = 0;
// console.info(schedule, duration, workingHours);

return {
TIME_ZONE = parseInt(workingHours.from.split('+')[1]);
// workingHours.from = workingHours.from.replace(/\+\d+/, '+' + TIME_ZONE);
// workingHours.to = workingHours.to.replace(/\+\d+/, '+' + TIME_ZONE);

schedule = invertSchedule(schedule);

setTimeStamps(schedule);
// console.log(schedule);
fixErrors(schedule);
// console.log(schedule);
// print(schedule);
var bestAttackTime = filterSchedule(schedule, workingHours, duration);
var startTimesToAttack = getStartTimes(bestAttackTime, duration);

// console.log(bestAttackTime);

// console.log(startTimesToAttack.map(function (time) {
// return toStr(time);
// }));

var replacer = function (match, p) {
// var timeDiff = TIME_ZONE * 60 * 60 * 1000;
var format = {
'%HH': function (time) {
var hours = new Date(time).getHours();

return addZero(hours);
},
'%MM': function (time) {
var minutes = new Date(time).getMinutes();

return addZero(minutes);
},
'%DD': function (time) {
var days = {
0: 'ВС',
1: 'ПН',
2: 'ВТ',
3: 'СР',
4: 'ЧТ'
};
var day = new Date(time).getDay();

/**
* Найдено ли время
* @returns {Boolean}
*/
return days[day];
}
};

return format[p](startTimesToAttack[index]);
};

return {
exists: function () {
return false;

return startTimesToAttack.length > 0;
},

/**
* Возвращает отформатированную строку с часами для ограбления
* Например,
* "Начинаем в %HH:%MM (%DD)" -> "Начинаем в 14:59 (СР)"
* @param {String} template
* @returns {String}
*/
format: function (template) {
return template;
if (!this.exists()) {

return '';
}

return template.replace(/(%\S\S)/g, replacer);
},

/**
* Попробовать найти часы для ограбления позже [*]
* @star
* @returns {Boolean}
*/
tryLater: function () {
if (index < startTimesToAttack.length - 1) {
index++;

return true;
}

return false;
}
};
};

function fixErrors(schedule) {
Object.keys(schedule).forEach(function (name) {
var busyTime = schedule[name];
var delIndexes = [];
for (var i = 0; i < busyTime.length; i++) {
if (busyTime[i].from > busyTime[i].to) {
delIndexes.push(i);
}
}

delIndexes.forEach(function (index) {
busyTime.splice(index, 1);
});
});
}

function addZero(digit) {
if (digit < 10) {

return '0' + digit;
}

return digit;
}

function getStartTimes(bestAttackTime, duration) {
if (bestAttackTime.length === 0) {

return [];
}

var times = [];
process(bestAttackTime, times, duration * 60 * 1000);

return times;
}

function process(intervals, result, durationInMillisecond) {
var halfHour = 30 * 60 * 1000;
var index = 0;

while (index < intervals.length) {
var currentTime = intervals[index].from;
result.push(currentTime);
var possibleTime = currentTime + halfHour;
while (check(possibleTime, durationInMillisecond, intervals)) {
result.push(possibleTime);
possibleTime += halfHour;
}
index = getIndex(intervals, possibleTime);
if (Math.ceil(index) === index) {
index += 1;
} else {
index = Math.ceil(index);
}
}
}

function getIndex(intervals, possibleTime) {
for (var i = 0.0; i < intervals.length - 1; i ++) {
if (intervals[i].from <= possibleTime &&
possibleTime <= intervals[i].to) {

return i;
} else if (intervals[i].to <= possibleTime &&
possibleTime <= intervals[i + 1].from) {

return i + 0.5;
}
}

if (intervals[intervals.length - 1].from <= possibleTime &&
possibleTime <= intervals[intervals.length - 1].to) {

return intervals.length - 1;
}

if (intervals[intervals.length - 1].to <= possibleTime) {

return intervals.length - 0.5;
}
}

function check(possibleTime, durationInMillisecond, intervals) {
var index = getIndex(intervals, possibleTime);
try {
if (possibleTime + durationInMillisecond <= intervals[index].to) {

return true;
}
} catch (e) {

return false;
}

return false;
}

function filterSchedule(schedule, workingHours, duration) {
var names = Object.keys(schedule);

var bankSchedule = [];
['ПН ', 'ВТ ', 'СР '].forEach(function (day) {
bankSchedule.push({
from: getTimeStamp(day + workingHours.from),
to: getTimeStamp(day + workingHours.to)
});
});

var tIntrsc = getSchedulesIntersection(bankSchedule, schedule[names[0]]);
for (var i = 1; i < names.length; i++) {
tIntrsc = getSchedulesIntersection(schedule[names[i]], tIntrsc);
}

var durationInMilliseconds = duration * 60 * 1000;

return tIntrsc.filter(function (time) {
return time.from + durationInMilliseconds <= time.to;
});
}

function getSchedulesIntersection(schedule1, schedule2) {
var intersections = [];
schedule1.forEach(function (sc1) {
schedule2.forEach(function (sc2) {
var intersection = getTimeIntersection(sc1, sc2);
if (intersection.exist) {
intersections.push(intersection);
}
});
});

return intersections;
}

function invertSchedule(schedule) {
var _new = {};
Object.keys(schedule).forEach(function (name) {
var busyTime = schedule[name];
var freeTime = [];

freeTime.push({
from: 'ПН 00:00+23', // + TIME_ZONE.toString()
to: busyTime[0].from
});

for (var i = 1; i < busyTime.length; i++) {
freeTime.push({
from: busyTime[i - 1].to,
to: busyTime[i].from
});
}

freeTime.push({
from: busyTime[busyTime.length - 1].to,
to: 'ВС 23:59+23' // + TIME_ZONE.toString()
});
_new[name] = freeTime;
});

return _new;
}

function setTimeStamps(schedule) {
Object.keys(schedule).forEach(function (name) {
schedule[name].forEach(function (time) {
time.from = getTimeStamp(time.from);
time.to = getTimeStamp(time.to);
});
});
}

function getTimeIntersection(firstRange, secondRange) {
var intersection = {
exist: false,
from: Math.max(firstRange.from, secondRange.from),
to: Math.min(firstRange.to, secondRange.to)
};

if (intersection.from < intersection.to) {
intersection.exist = true;
}

return intersection;
}

function getTimeStamp(date) {
var toFullDate = {
ПН: '01-04-2016',
ВТ: '01-05-2016',
СР: '01-06-2016',
ЧТ: '01-07-2016',
ПТ: '01-08-2016',
СБ: '01-09-2016',
ВС: '01-10-2016'
};
var day = date.split(' ')[0];
var time = date.split(' ')[1];

var _date = new Date(toFullDate[day] + ' ' + time);
_date.setHours(_date.getHours() + TIME_ZONE);

return _date.getTime();
}