const log = require('../utils/log.utils'); const db = require('./dbAccess.services'); const clean = require('../utils/sanitizer.utils'); const pis = require('../services/pis.services'); async function findByHeadcodeToday(headcode) { const sanitizedHeadcode = clean.removeNonAlphanumeric(headcode); log.out(`trainServiceServices.findByHeadcode: Searching for headcode ${sanitizedHeadcode}`, 'dbug'); const now = new Date(); const dayMap = ['su', 'm', 't', 'w', 'th', 'f', 's']; const shortDay = dayMap[now.getDay()]; // Fetch short day from map const query = { headcode: sanitizedHeadcode, scheduleStartDate: {$lte: now}, scheduleEndDate: {$gte: now}, daysRun: {$in: [shortDay]} }; const queryData = await db.query('timetable', query); let trainData = await parseTrains(queryData, now); let preparedData = []; for (const trainService in trainData) { // Search for PIS Code for each service let tiplocList = await getPublicStops(trainData[trainService]['stops']); const pisDetail = await pis.findByTiplocArray(tiplocList); trainData[trainService]['pis'] = pisDetail?.[0]?.['code'] ?? 'None'; preparedData.push(trainData[trainService]); } return preparedData; } module.exports = { findByHeadcodeToday, }; /* Internal Functions, not to be exported */ async function getPublicStops(data) { let tiplocList = []; for (const publicStop in data) { if (data[publicStop]['isPublic']) { tiplocList.push(data[publicStop]['tiploc']); } } return tiplocList; } async function parseTrains(data, date = new Date() { // Parses an array returned from a db-query and removes any service entries that don't apply to {date} // {date} shoule be a datetime object and defaults to now if not provided - as a general rule it should always be provided for clarity // At this point, the returned objects need sorting to ensure the correct object is returned. // C, N, O, P is the order - C being the preferred, then N, then O and finally P. // If stpindicator == "C" && trainUid (isSame as N, O or P entry) => DO NOT DISPLAY SERVICE ("C" records do not contain the headcode (signalling_id)) so an additional lookup needs to be performed for the trainUid. // If stpIndicator == "N" && trainUid (isSame as O or P entry) => Display this instead of "O", or "P" // If stpIndicaor == "O" && trainUid (isSame as P entry) => Display this instead of "P" // Obviously, remember that several trains can share a headcode, but the trainUid is unique for each service. // Probably best to loop through each return here and add to a new [], then if another entry supersedes it, overwrite it in the []. Then pass to the below part of the function to process the data for sending. // Maybe break in to a new function parseTrains() which can take in any dbquery array and remove any services that are not meant to be displayed based on the data provided. Maybe have a date as an input so it can be used in the future to fetch trains for a given date in the future - due to database cleaning in db-manager, past dates would need adjustments to how the database is cleaned leaving outdated services available. const parsedDate = data; return parsedData; };