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); let preparedData = []; for (const trainService in trainData) { // Search for PIS Code for each service const tiplocList = await getPublicStops(trainData[trainService]['stops']); if (tiplocList.length) { const pisDetail = await pis.findByTiplocArray(tiplocList); trainData[trainService]['pis'] = pisDetail?.[0]?.['code'] ?? 'None'; } else { trainData[trainService]['pis'] = '0015'; // Not in Service code } 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) { // Takes a single days data from a headcode query and returns only relevant services let trainUids = []; for (const i in data) { const trainUid = data[i]['trainUid']; if (!trainUids.includes(trainUid)) { data.push(trainUid); } } let parsedData = []; for (const i in trainUids) { const result = await findByTrainUid(trainUids[i]); parsedData.push(result); } return parsedData; } async function findByTrainUid(uid, date = new Date()) { // Date defaults to today const query = { trainUid: uid, scheduleStartDate: {$lte: date}, scheduleEndDate: {$gte: date} }; const queryData = await db.query('timetable', query); let c = []; let n = []; let o = []; let p = []; for (const serviceDetail of queryData) { const trainUid = serviceDetail['trainUid']; switch (serviceDetail['stpIndicator']) { // This won't work without further post procesing case 'C': c.push(trainUid); break; case 'N': if (!c.includes(trainUid)) { n.push(trainUid); } break; case 'O': if (!c.includes(trainUid) && !n.includes(trainUid)) { o.push(trainUid); } break; case 'P': if (!c.includes(trainUid) && !n.includes(trainUid) && !o.includes(trainUid)) { p.push(trainUid); } break; } } } /* Thoughts: async function findByTrainUid(uid, date = new Date()) { const query = { trainUid: uid, scheduleStartDate: { $lte: date }, scheduleEndDate: { $gte: date } }; const queryData = await db.query('timetable', query); if (queryData.length === 0) { // Handle empty queryData return { c: [], n: [], o: [], p: [] }; } const trainUidSet = new Set(); const trainUidStatus = {}; // Track the status of each trainUid for (const serviceDetail of queryData) { const trainUid = serviceDetail['trainUid']; const stpIndicator = serviceDetail['stpIndicator']; if (!trainUidStatus[trainUid]) { trainUidStatus[trainUid] = { hasO: false, hasN: false, hasC: false }; } if (stpIndicator === 'O') { trainUidStatus[trainUid].hasO = true; } else if (stpIndicator === 'N') { trainUidStatus[trainUid].hasN = true; } else if (stpIndicator === 'C') { trainUidStatus[trainUid].hasC = true; } trainUidSet.add(trainUid); } const c = []; const n = []; const o = []; const p = []; for (const serviceDetail of queryData) { const trainUid = serviceDetail['trainUid']; const stpIndicator = serviceDetail['stpIndicator']; if (stpIndicator === 'C') { continue; // Skip 'C' entries } if (stpIndicator === 'N' && !trainUidStatus[trainUid].hasC) { n.push(trainUid); } else if (stpIndicator === 'O' && !trainUidStatus[trainUid].hasN && !trainUidStatus[trainUid].hasC) { o.push(trainUid); } else if (stpIndicator === 'P' && !trainUidStatus[trainUid].hasN && !trainUidStatus[trainUid].hasO && !trainUidStatus[trainUid].hasC) { p.push(trainUid); } } return { c, n, o, p }; } */