lib/parks/walibi/walibiholland.js
import moment from 'moment-timezone';
import fetch from 'node-fetch';
import {Park} from '../park.js';
import {entityType, queueType, scheduleType} from '../types.js';
import dotenv from 'dotenv';
dotenv.config();
/**
* Walibi Holland Park Object
* Make sure all environment variables are set in an .env file which should be in the main location.
* Not setting these variables will make the module exit early without returning data.
*
* This class is here to fetch the POI data and to attach queue times data to it.
* After the fetches this data is send to the end user and from there he could do whatever he wants to do.
*
* Most park specific parameters are set already
* @class
*/
export class WalibiHolland extends Park {
/**
* Create a new Walibi Holland Park object
* @param {object} options
*/
constructor(options = {}) {
options.name = options.name || 'Walibi Holland';
options.timezone = options.timezone || 'Europe/Amsterdam';
// Setting the cute fountain at the entrance as parks location
options.latitude = 52.4390338;
options.longitude = 5.7665651;
// Options for our park Object
options.supportswaittimes = true;
options.supportsschedule = false;
options.supportsrideschedules = false;
options.fastPass = true;
options.FastPassReturnTimes = false;
// API options
options.apiUrl = options.apiUrl || process.env.WALIBIHOLLAND_APIURL;
options.apiBase = options.apiBase || process.env.WALIBIHOLLAND_APIBASE;
// Language settings
options.languages = options.languages || process.env.LANGUAGES;
options.langoptions = options.langoptions || `{'en', 'de', 'nl'}`;
super(options);
// Check for existance
if (!this.config.apiUrl) throw new Error('Missing Walibi Holland apiUrl!');
if (!this.config.apiBase) throw new Error('Missing Walibi Holland apiBase!');
if (!this.config.languages) {
this.config.languages = 'en';
};
}
/**
* Get All POIS of Walibi Holland
* This data contains all the POIS in Walibi Holland, limited to their fast-lane services
* @return {string} All Walibi Holland POIS with queuetimes
*/
async getQueue() {
return fetch(this.config.apiUrl,
{
method: 'GET',
},
)
.then((res) => res.json())
.then((rideData) => {
const poi = [];
rideData.forEach((ride) => {
let waitTime = '0';
let state = queueType.closed;
let active = false;
if (ride.name !== 'Dummy1') { // They have a dummy ride to sell single shots in their fast-lane, mind=blown
if (ride.useVirtualQueue == true) { // VirtQueue enabled
waitTime = Math.round(ride.waitTimeMins); // Stupid API serves random numbers like 0.00010358, let's round them.
state = queueType.operating;
active = true;
} else { // No virtQueue found, use the normal queue instead
waitTime = ride.minWait / 60; // Walibi has some calculation issues or sth so divide our result by 60
state = queueType.operating;
active = true;
}
if (ride.state === 'closed_indefinitely') { // Ride is listed as Down, however, when all rides are closing for the night, it has the same status lol.
state = queueType.down;
active = false;
} else if (ride.state === 'not_operational') { // Ride is not operational (today?)
state = queueType.closed;
active = false;
}
// Declare other states when park reopens
const updated = moment(ride.bufferQueueLastModified).format();
let fastPass = false;
if (ride.useVirtualQueue === true || ride.useVirtualQueue === false) {
fastPass = true;
}
// set location the hardcoded way because they're initially listed in a seperate api
let lat = undefined;
let lon = undefined;
let area = undefined;
if (ride.name === 'Lost Gravity') {
lat = JSON.parse('52.442628');
lon = JSON.parse('5.766199');
area = 'Zero Zone';
} else if (ride.name === 'El Rio Grande') {
lat = JSON.parse('52.440264');
lon = JSON.parse('5.764119');
area = 'Exotic';
} else if (ride.name === 'Goliath') {
lat = JSON.parse('52.439853309732');
lon = JSON.parse('5.7610387061724');
area = 'Speedzone';
} else if (ride.name === 'Untamed') {
lat = JSON.parse('52.442665');
lon = JSON.parse('5.761206');
area = 'Wilderness';
} else if (ride.name === 'Space Shot') {
lat = JSON.parse('52.441688');
lon = JSON.parse('5.761082');
area = 'Speedzone';
} else if (ride.name === 'Speed of Sound') {
lat = JSON.parse('52.440535');
lon = JSON.parse('5.767824');
area = 'W.A.B. Plaza';
} else if (ride.name === 'Xpress: Platform 13') {
lat = JSON.parse('52.439772689391');
lon = JSON.parse('5.7654926519984');
area = 'Mainstreet';
} else if (ride.name === 'Crazy River') {
lat = JSON.parse('52.441924');
lon = JSON.parse('5.764769');
area = 'Zero Zone';
} else if (ride.name === 'Condor') {
lat = JSON.parse('52.440404970358');
lon = JSON.parse('5.7618163417733');
area = 'Exotic';
} else if (ride.name === 'Blast') {
lat = JSON.parse('52.441894');
lon = JSON.parse('5.763487');
area = 'Wilderness';
}
// POI Object with queues
const poiData = {
name: ride.name,
id: 'WalibiHolland_' + ride.shortId,
state: state,
active: active,
waitTime: waitTime,
changedAt: updated,
location: {
latitude: lat,
longitude: lon,
area: area,
},
meta: {
type: entityType.ride,
fastPass: fastPass,
},
};
poi.push(poiData);
}
});
return Promise.resolve(poi);
});
}
/**
* Get All Operating Hours of Walibi Holland
* This data contains all the Operating Hours in Walibi Holland, fetched with currentyear.
* @return {string} All Walibi Holland calendar data
*/
async getOpHours() {
const currentYear = moment().format('YYYY');
return fetch(
this.config.apiBase +
`/calendar/${currentYear}?_format=json`,
{
method: 'GET',
},
)
.then((res) => res.json())
.then((json) => {
const Calendar = [];
// Execute Calendar stuff here
// The calendar provides data for the whole year, however, we don't want past data.
Object.keys(json.opening_hours).forEach((key) => {
const now = moment().format('MM') + '\/' + moment().format('DD');
// Only continue if our hit is AFTER yesterday
if (moment(key).isSameOrAfter(moment(now))) {
let state = json.opening_hours[key].status;
let open = undefined;
let close = undefined;
const datesplit = key.split('/');
const date = currentYear + '-' + datesplit[0] + '-' + datesplit[1];
// Park is closed, nothing returned
if (state === 'closed') {
state = scheduleType.closed;
open = moment(`${date} 23:59`, 'YYYY-MM-DD HH:mm a', `${this.config.Timezone}`).format();
close = moment(`${date} 23:59`, 'YYYY-MM-DD HH:mm a', `${this.config.Timezone}`).format();
// Park is open, but sold out, strangely enough operating hours are removed as well
} else if (state === 'soldout') {
open = moment(`${date} 10:00`, 'YYYY-MM-DD HH:mm a', `${this.config.Timezone}`).format();
close = moment(`${date} 23:00`, 'YYYY-MM-DD HH:mm a', `${this.config.Timezone}`).format();
state = scheduleType.operating;
// Park is operating as normal
} else {
state = scheduleType.operating;
open = moment(`${date} ${json.opening_hours[key].mo_time}`, 'YYYY-MM-DD HH:mm a', `${this.config.Timezone}`).format();
close = moment(`${date} ${json.opening_hours[key].mc_time}`, 'YYYY-MM-DD HH:mm a', `${this.config.Timezone}`).format();
}
// Set the hours object
const hourobj = {
openingTime: open,
closingTime: close,
date: date,
type: state,
};
Calendar.push(hourobj);
}
});
return Promise.resolve(Calendar);
});
}
}
export default WalibiHolland;