2020-11-03 23:00:17 +00:00
|
|
|
import { parse } from 'fecha';
|
|
|
|
|
|
|
|
class Carpark {
|
2020-11-10 14:01:45 +00:00
|
|
|
private _startDT: Date = new Date(0);
|
|
|
|
private _endDT: Date = new Date(0);
|
2020-11-03 23:00:17 +00:00
|
|
|
private _dayLength: number = 60 * 60 * 24;
|
|
|
|
private _hourLength: number = 60 * 60;
|
|
|
|
private _validDays: number[] = [1, 2, 3, 4, 5]; // Monday, Tuesday, Wednesday, Thursday, Friday
|
|
|
|
private _validStart: number = this._hourLength * 8; // 8AM // 08:00
|
|
|
|
private _validEnd: number = this._hourLength * 18; // 6PM // 18:00
|
|
|
|
private _longPrice = 7.5;
|
|
|
|
private _shortPrice = 1.1;
|
|
|
|
private _secondPrice: number = this._shortPrice / this._hourLength;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if a specific timestamp is a valid date
|
|
|
|
* @param workTime
|
|
|
|
*/
|
|
|
|
private _isValidTime(workTime: number): boolean {
|
|
|
|
const day = new Date(workTime * 1000).getDay();
|
|
|
|
|
|
|
|
if (this._validDays.indexOf(day) > -1) {
|
|
|
|
const dayBase: number = ~~(workTime / this._dayLength) * this._dayLength;
|
|
|
|
const dayPosition: number = workTime - dayBase;
|
|
|
|
|
|
|
|
return dayPosition >= this._validStart && dayPosition < this._validEnd - 1;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculate short term parking costs
|
|
|
|
*/
|
|
|
|
private _calcShortTerm(): number {
|
|
|
|
const startSeconds: number = this._startDT.getTime() / 1000;
|
|
|
|
const endSeconds: number = this._endDT.getTime() / 1000;
|
|
|
|
let workTime: number;
|
|
|
|
|
|
|
|
let validHours = 0;
|
|
|
|
let startHourPart = 0;
|
|
|
|
|
|
|
|
// Calculate Start Hour
|
|
|
|
const startBaseHour: number = ~~(startSeconds / this._hourLength) * this._hourLength;
|
|
|
|
|
|
|
|
// Calculate End Hour
|
|
|
|
const endBaseHour: number = ~~(endSeconds / this._hourLength) * this._hourLength;
|
|
|
|
|
|
|
|
// Check if the very first portion of the hour is valid
|
|
|
|
if (this._isValidTime(startSeconds)) {
|
|
|
|
startHourPart = this._hourLength - (startSeconds - startBaseHour);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Go to the next hour after the initial start
|
|
|
|
workTime = startBaseHour + this._hourLength;
|
|
|
|
|
|
|
|
// If there's more of an hours worth of time then loop through the next hours
|
|
|
|
if (endBaseHour - workTime > this._hourLength) {
|
|
|
|
do {
|
|
|
|
validHours = validHours + (this._isValidTime(workTime) ? 1 : 0);
|
|
|
|
workTime = workTime + this._hourLength;
|
|
|
|
} while (workTime <= endBaseHour);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sum it all
|
|
|
|
return startHourPart * this._secondPrice + validHours * this._shortPrice;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculate long term parking costs
|
|
|
|
* @returns {number}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
private _calcLongTerm(): number {
|
|
|
|
// convert to time stamps and make them second based
|
|
|
|
const startSeconds: number = this._startDT.getTime() / 1000;
|
|
|
|
const endSeconds: number = this._endDT.getTime() / 1000;
|
|
|
|
|
|
|
|
// Very start of the first day
|
|
|
|
const startBaseSeconds: number = ~~(startSeconds / this._dayLength) * this._dayLength;
|
|
|
|
|
|
|
|
// Very end of the second day
|
|
|
|
const endBaseSeconds: number = ~~(endSeconds / this._dayLength) * this._dayLength + this._dayLength;
|
|
|
|
|
|
|
|
// Subtract the start seconds from the end seconds
|
|
|
|
const distance: number = endBaseSeconds - startBaseSeconds;
|
|
|
|
|
|
|
|
// divide them by number of seconds in a day and multiply by cost
|
|
|
|
|
|
|
|
return (distance / this._dayLength) * this._longPrice;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The public calculate method
|
|
|
|
* @param start
|
|
|
|
* @param end
|
|
|
|
* @param mode
|
|
|
|
* @returns {number}
|
|
|
|
*/
|
|
|
|
calculate(start: string, end: string, mode: string = 'longterm'): number {
|
|
|
|
let workVal = 0.0;
|
2020-11-10 14:01:45 +00:00
|
|
|
this._startDT = <Date>parse(start, 'DD/MM/YYYY HH:mm:ssZ');
|
|
|
|
this._endDT = <Date>parse(end, 'DD/MM/YYYY HH:mm:ssZ');
|
2020-11-03 23:00:17 +00:00
|
|
|
|
2020-11-10 14:01:45 +00:00
|
|
|
if (this._endDT.getTime() <= this._startDT.getTime()) return workVal;
|
2020-11-03 23:00:17 +00:00
|
|
|
switch (mode.toLowerCase()) {
|
|
|
|
case 'short':
|
|
|
|
case 'shortterm':
|
|
|
|
workVal = this._calcShortTerm();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'long':
|
|
|
|
case 'longterm':
|
|
|
|
workVal = this._calcLongTerm();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
|
|
|
|
return parseFloat(workVal.toFixed(2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default Carpark;
|