-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcalculator.js
executable file
·125 lines (101 loc) · 3.17 KB
/
calculator.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
const input = require('./input.json');
const expectedOutput = require('./expectedOutput.json');
// Approach
// - Loop through all input bookings.
// - Discard any bookings that don't meet the business rules.
// - Add remaining valid bookings to new output array.
const hourInMilliseconds = 60 * 60 * 1000;
const saturdayRate = 45.91;
const sundayRate = 60.85;
const nightRate = 42.93;
const dayRate = 38;
let rate = '';
(() => {
const output = input.reduce((acc, booking) => {
let newBooking = { ...booking };
if (hasIncorrectOffset(booking.from, booking.to)) {
acc.push(formatBooking(newBooking));
return acc;
}
const from = new Date(newBooking.from);
const to = new Date(newBooking.to);
if (isLessThan1Hour(from, to)) {
acc.push(formatBooking(newBooking));
return acc;
}
if (isGreaterThan24Hours(from, to)) {
acc.push(formatBooking(newBooking));
return acc;
}
if (hasEndedBeforeStarted(from, to)) {
acc.push(formatBooking(newBooking));
return acc;
}
if (isSaturday(from, to)) { // TODO: can use SWITCH too
rate = calculateRate(from, to, 'saturday');
newBooking = formatBooking(newBooking, true, rate);
} else if (isSunday(from, to)) {
rate = calculateRate(from, to, 'sunday');
newBooking = formatBooking(newBooking, true, rate);
} else if (isNight(to)) {
rate = calculateRate(from, to, 'night');
newBooking = formatBooking(newBooking, true, rate);
} else {
rate = calculateRate(from, to);
newBooking = formatBooking(newBooking, true, rate);
}
// Booking is valid at this point, lets return it.
acc.push(newBooking);
return acc;
}, []);
console.log('RESULT', JSON.stringify(output) === JSON.stringify(expectedOutput));
})();
function isLessThan1Hour(from, to) {
const diff = Math.abs(from - to);
return diff < hourInMilliseconds;
}
function isGreaterThan24Hours(from, to) {
const diff = Math.abs(from - to);
return diff > (hourInMilliseconds * 24);
}
function hasEndedBeforeStarted(from, to) {
return to < from;
}
function hasIncorrectOffset(from, to) {
if (!from.includes('+11:00')) return true;
if (!to.includes('+11:00')) return true;
return false;
}
function isSaturday(from) {
if (from.getDay() === 6) return true;
return false;
}
function isSunday(from) {
if (from.getDay() === 0) return true;
return false;
}
function isNight(to) {
const toNight = to.getHours();
if (toNight >= 20) return true;
if (toNight <= 6) return true;
return false;
}
function calculateRate(from, to, type) {
const diff = Math.abs(from - to);
const hours = diff / hourInMilliseconds;
if (type == 'saturday') return hours * saturdayRate;
if (type == 'sunday') return hours * sundayRate;
if (type == 'night') return hours * nightRate;
// TODO: include error handling / else
return hours * dayRate;
}
function formatBooking(booking, isValid = false, total = 0) {
return {
...booking,
isValid,
total: parseFloat(total.toFixed(2))
};
}
module.exports = {
isLessThan1Hour, isGreaterThan24Hours, hasEndedBeforeStarted, hasIncorrectOffset, isSaturday, isSunday, isNight, calculateRate, formatBooking
};