Further rewrite of trainService.services

Signed-off-by: Fred Boniface <fred@fjla.uk>
This commit is contained in:
Fred Boniface 2023-12-01 21:40:25 +00:00
parent 89cd3630d4
commit f91609e0d2
5 changed files with 139 additions and 45 deletions

8
package-lock.json generated
View File

@ -24,7 +24,7 @@
"zlib": "^1.0.5" "zlib": "^1.0.5"
}, },
"devDependencies": { "devDependencies": {
"@owlboard/ts-types": "^0.1.3", "@owlboard/ts-types": "^0.1.5",
"@types/jest": "^29.5.3", "@types/jest": "^29.5.3",
"eslint": "^8.39.0", "eslint": "^8.39.0",
"jest": "^29.6.2", "jest": "^29.6.2",
@ -1983,9 +1983,9 @@
} }
}, },
"node_modules/@owlboard/ts-types": { "node_modules/@owlboard/ts-types": {
"version": "0.1.3", "version": "0.1.5",
"resolved": "https://git.fjla.uk/api/packages/OwlBoard/npm/%40owlboard%2Fts-types/-/0.1.3/ts-types-0.1.3.tgz", "resolved": "https://git.fjla.uk/api/packages/OwlBoard/npm/%40owlboard%2Fts-types/-/0.1.5/ts-types-0.1.5.tgz",
"integrity": "sha512-BKi/tWvA0SN2rgt2GnFnSXEXzG3DNjeTm0ojVuMElnok9MJ9IniTXRjdAdjm+fe5ShebH6EKacO5f1MDAD3qJw==", "integrity": "sha512-bbCSDpwAJSUKFHcT3QwXAutlBp02QqAXvobg/wGm8zoaAeWNozWeJSdceMzgse6Ywc1aGamP4w20hlTREl7f8g==",
"dev": true, "dev": true,
"license": "GPL-3.0-or-later" "license": "GPL-3.0-or-later"
}, },

View File

@ -33,7 +33,7 @@
"zlib": "^1.0.5" "zlib": "^1.0.5"
}, },
"devDependencies": { "devDependencies": {
"@owlboard/ts-types": "^0.1.3", "@owlboard/ts-types": "^0.1.5",
"@types/jest": "^29.5.3", "@types/jest": "^29.5.3",
"eslint": "^8.39.0", "eslint": "^8.39.0",
"jest": "^29.6.2", "jest": "^29.6.2",

View File

@ -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<SimpleService[]> {
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<string, { hasC: boolean; hasN: boolean; hasO: boolean; hasP: boolean }> = {};
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:

View File

@ -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<TrainServices[]> {
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
}

View File

@ -18,3 +18,9 @@ export function getFindByHeadcodePipeline(query: any) {
}, },
]; ];
} }
export function getFindByTrainUidPipeline(query: any) {
return [{
'$match': query,
},{'$project': {'_id': 0}}]
}