From f91609e0d2afc04fc4c71005dbc2306360925451 Mon Sep 17 00:00:00 2001 From: Fred Boniface Date: Fri, 1 Dec 2023 21:40:25 +0000 Subject: [PATCH] Further rewrite of trainService.services Signed-off-by: Fred Boniface --- package-lock.json | 8 +- package.json | 2 +- src/services/trainService.services2.ts | 128 +++++++++++++++++++++++++ src/services/trainService.services2ts | 40 -------- src/utils/trainService.utils.ts | 6 ++ 5 files changed, 139 insertions(+), 45 deletions(-) create mode 100644 src/services/trainService.services2.ts delete mode 100644 src/services/trainService.services2ts diff --git a/package-lock.json b/package-lock.json index 16ec17e..bdf5461 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "zlib": "^1.0.5" }, "devDependencies": { - "@owlboard/ts-types": "^0.1.3", + "@owlboard/ts-types": "^0.1.5", "@types/jest": "^29.5.3", "eslint": "^8.39.0", "jest": "^29.6.2", @@ -1983,9 +1983,9 @@ } }, "node_modules/@owlboard/ts-types": { - "version": "0.1.3", - "resolved": "https://git.fjla.uk/api/packages/OwlBoard/npm/%40owlboard%2Fts-types/-/0.1.3/ts-types-0.1.3.tgz", - "integrity": "sha512-BKi/tWvA0SN2rgt2GnFnSXEXzG3DNjeTm0ojVuMElnok9MJ9IniTXRjdAdjm+fe5ShebH6EKacO5f1MDAD3qJw==", + "version": "0.1.5", + "resolved": "https://git.fjla.uk/api/packages/OwlBoard/npm/%40owlboard%2Fts-types/-/0.1.5/ts-types-0.1.5.tgz", + "integrity": "sha512-bbCSDpwAJSUKFHcT3QwXAutlBp02QqAXvobg/wGm8zoaAeWNozWeJSdceMzgse6Ywc1aGamP4w20hlTREl7f8g==", "dev": true, "license": "GPL-3.0-or-later" }, diff --git a/package.json b/package.json index 734e2cc..03ed62c 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "zlib": "^1.0.5" }, "devDependencies": { - "@owlboard/ts-types": "^0.1.3", + "@owlboard/ts-types": "^0.1.5", "@types/jest": "^29.5.3", "eslint": "^8.39.0", "jest": "^29.6.2", diff --git a/src/services/trainService.services2.ts b/src/services/trainService.services2.ts new file mode 100644 index 0000000..ffdafca --- /dev/null +++ b/src/services/trainService.services2.ts @@ -0,0 +1,128 @@ +import { logger } from "../utils/logger.utils"; +import { findByTiplocArray } from "../services/pis.services" +import { queryAggregate } from "./dbAccess.services"; +import { getFindByHeadcodePipeline, getFindByTrainUidPipeline } from "../utils/trainService.utils" +import { removeNonAlphanumeric } from "../utils/sanitizer.utils" + +import type { TrainServices, Service, Stop, SimpleService } from "@owlboard/ts-types"; + +export async function findByHeadcode(headcode: string, date: Date | string): Promise { + const sanitizedHeadcode = removeNonAlphanumeric(headcode); + logger.debug(`trainServices.findByHeadcode: Searching for trains by headcode: ${headcode}`) + + // If 'now' then generate a new Date now, else use the provided date, then set time to 1200. + const searchDate = (date === "now") ? new Date() : new Date(date); + searchDate.setHours(12, 0, 0); + + // Get the 'shortDay' + const shortDay = getShortDay(searchDate) + + const query = { + headcode: sanitizedHeadcode, + scheduleStartDate: { $lte: searchDate }, + scheduleEndDate: { $gte: searchDate }, + daysRun: { $in: [shortDay] }, + }; + const pipeline = getFindByHeadcodePipeline(query) + + const result: SimpleService[] = await queryAggregate("timetable", pipeline) as SimpleService[] + + const services = filterServices(result); + + return services; +} + +export async function findByTrainUid(uid: string, date: Date | string = new Date()) { + // Set the correct date - whether a date or "now" was passed to function + let queryDate: Date; + if (date instanceof Date) { + queryDate = date; + } else { + queryDate = new Date(); + } + + // Build query + const query = { + trainUid: uid, + scheduleStartDate: { $lte: queryDate }, + scheduleEndDate: { $gte: queryDate }, + daysRun: { $in: [getShortDay(queryDate)] } + } + const pipeline = getFindByTrainUidPipeline(query) + + const result = await queryAggregate("timetable", pipeline) as Service[] + + let services = filterServices(result) as Service[] + + // Next up is the public stops filter, followed by the PIS filter. +} + +// Internal Functions: + +// Outputs the standard 'shortday' string from a Date. +function getShortDay(day: Date): string { + const dayMap = ["su", "m", "t", "w", "th", "f", "s"]; + const shortDay = dayMap[day.getDay()]; + return shortDay +} + +// Filters services using their STP indicator so that over-riding entries are returned correctly +function filterServices(services: SimpleService[]): (SimpleService[]) { + let stpIndicators: Record = {}; + let filteredServices: SimpleService[] = [] + + for (const service of services) { + const trainUid = service["trainUid"], stpIndicator = service["stpIndicator"] + + // Creates the stpIndicators array: + if (!stpIndicators[trainUid]) { + stpIndicators[trainUid] = { + hasC: false, hasN: false, hasO: false, hasP: false, + } + } + + if (stpIndicator === "C") { + stpIndicators[trainUid].hasC = true; + } + if (stpIndicator === "N") { + stpIndicators[trainUid].hasN = true; + } + if (stpIndicator === "O") { + stpIndicators[trainUid].hasO = true; + } + if (stpIndicator === "P") { + stpIndicators[trainUid].hasP = true; + } + } + + // Iterate each service, and only output one service matching each trainUid, + // C > N > O > P is the order, with C being prioritised over other STP types. + for (const service of services) { + const trainUid = service["trainUid"] + const thisStpIndicators = stpIndicators[trainUid]; + const stpIndicator = service["stpIndicator"]; + + if (stpIndicator === "C") { + continue; + } + if (stpIndicator === "N" && !thisStpIndicators.hasC) { + filteredServices.push(service); + } else if ( + stpIndicator === "O" && + !thisStpIndicators.hasC && + !thisStpIndicators.hasN + ) { + filteredServices.push(service); + } else if ( + stpIndicator === "P" && + !thisStpIndicators.hasC && + !thisStpIndicators.hasN && + !thisStpIndicators.hasO + ) { + filteredServices.push(service); + } + } + return filteredServices; +} + +// Local Types: diff --git a/src/services/trainService.services2ts b/src/services/trainService.services2ts deleted file mode 100644 index 6c66bb1..0000000 --- a/src/services/trainService.services2ts +++ /dev/null @@ -1,40 +0,0 @@ -import { logger } from "../utils/logger.utils"; -import { findByTiplocArray } from "../services/pis.services" -import { queryAggregate } from "./dbAccess.services"; -import { getFindByHeadcodePipeline } from "../utils/trainService.utils" -import { removeNonAlphanumeric } from "../utils/sanitizer.utils" - -import type { TrainServices, Service, Stop } from "@owlboard/ts-types"; -import type { Document } from "mongodb"; - -export async function findByHeadcode(headcode: string, date: Date | string): Promise { - const sanitizedHeadcode = removeNonAlphanumeric(headcode); - logger.debug(`trainServices.findByHeadcode: Searching for trains by headcode: ${headcode}`) - - // If 'now' then generate a new Date now, else use the provided date, then set time to 1200. - const searchDate = (date === "now") ? new Date() : new Date(date); - searchDate.setHours(12, 0, 0); - - // Get the 'shortDay' - const shortDay = getShortDay(searchDate) - - const query = { - headcode: sanitizedHeadcode, - scheduleStartDate: { $lte: searchDate }, - scheduleEndDate: { $gte: searchDate }, - daysRun: { $in: [shortDay] }, - }; - const pipeline = getFindByHeadcodePipeline(query) - // Before proceeding, I need to check the return from the database to ensure that it - // is of type Service[] - for this use the Aggregate function in Compass. - const result: Service[] = await queryAggregate("timetable", pipeline) as Service[] - - // The Filter Services function needs writing - possibly moving to utils as it is long. -} - -// Outputs the standard 'shortday' string from a Date. -function getShortDay(day: Date): string { - const dayMap = ["su", "m", "t", "w", "th", "f", "s"]; - const shortDay = dayMap[day.getDay()]; - return shortDay -} \ No newline at end of file diff --git a/src/utils/trainService.utils.ts b/src/utils/trainService.utils.ts index 7cef600..1920c0c 100644 --- a/src/utils/trainService.utils.ts +++ b/src/utils/trainService.utils.ts @@ -17,4 +17,10 @@ export function getFindByHeadcodePipeline(query: any) { }, }, ]; +} + +export function getFindByTrainUidPipeline(query: any) { + return [{ + '$match': query, +},{'$project': {'_id': 0}}] } \ No newline at end of file