tw-shift-schedule
Version:
153 lines (131 loc) • 4.41 kB
JavaScript
;
var lexer = require('./lexer');
var Causes = {
irregular: '不規律的工作',
longHours: '長時間工作',
nightShift: '夜班',
previousDayOverwork: '前一天長時間工作',
previousWeekOverwork: '前一週長時間工作',
previousMonthOvertime: '前一個月加班時數 > 100',
previousSixMonthsOvertime: '前六個月加班時數平均 > 45'
};
module.exports = { Causes: Causes, check: check
// 過勞定義 http://www.mqjh.tp.edu.tw/mediafile/1901/news/19/2016-1/22016-1-24-21-27-24-nf1.pdf
};function check(schedule) {
var causes = [];
// 只取出工作時段
var tokens = prettify(schedule.header.start, lexer(schedule.body)).filter(function (t) {
return t.type === 'work';
});
// 是否不規律
// 假設:如果每班的開始時間跟結束時間都不在同個小時內就當作不規律
var shiftStart;
var shiftEnd;
var t;
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = tokens[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
t = _step.value;
if (!shiftStart) {
shiftStart = t.time;
shiftEnd = shiftStart.clone().add(t.length, 'minutes');
continue;
}
if (shiftStart.hour() !== t.time.hour() && shiftEnd.hour() !== t.time.hour()) {
causes.push(Causes.irregular);
break;
}
}
// 長時間
// 假設平均工時大於 8 小時就是長時間
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
var avgLength = tokens.map(function (t) {
return t.length;
}).reduce(function (sum, x) {
return sum + x;
}, 0) / 60 / tokens.length;
if (avgLength > 8) {
causes.push(Causes.longHours);
}
// 夜班
// 下午 10 點 ~ 早上 6 點 = 夜班
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = tokens[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
t = _step2.value;
var startHour = t.time.hour();
var endHour = t.time.clone().add(t.length, 'minutes').hour();
if (startHour >= 22 || startHour <= 6 || endHour >= 22 || endHour <= 6) {
causes.push(Causes.nightShift);
break;
}
}
// 短期工作過重
// 前一日
// 前一日是否比平均工時還長?
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
if (tokens[tokens.length - 1].length / 60 > avgLength) {
causes.push(Causes.previousDayOverwork);
}
// 前一週
// 前一週是否比平均工時還長?
if (tokens.length >= 7 && lastAvgLenthInHour(tokens, 7) > avgLength) {
causes.push(Causes.previousWeekOverwork);
}
// 長期工作過重
// 加班時數
// 加班時數定義:每週 40 小時之外的工時
// 前一個月加班超過 100 小時
if (tokens.length >= 30 && sumLastLengthInHour(tokens, 30) - 40 * 4 > 100) causes.push(Causes.previousMonthOvertime);
// 前一至六個月平均加班超過 45 小時
if (tokens.length >= 180 && sumLastLengthInHour(tokens, 180) / 6 - 40 * 4 > 45) causes.push(Causes.previousSixMonthsOvertime);
return causes;
}
function lastAvgLenthInHour(tokens, length) {
return sumLastLengthInHour(tokens, length) / length;
}
function sumLastLengthInHour(tokens, length) {
var l = 0;
for (var i = tokens.length - 1; i > tokens.length - 1 - length; i--) {
l += tokens[i].length;
}
return l / 60;
}
function prettify(startTime, tokens) {
return tokens.map(function (t) {
return { type: t.type, length: t.value.length, line: t.line, time: offset2time(startTime, t.offset) };
});
}
function offset2time(startTime, offset) {
return startTime.clone().add(offset, 'minutes');
}