TimetableAPI-Upgrade #64
@ -44,7 +44,10 @@ async function findByHeadcodeToday(headcode: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finds a train by its headcode value
|
// Finds a train by its headcode value
|
||||||
async function findByHeadcode(date: string | Date, headcode: string): Promise<TrainServices[]> {
|
async function findByHeadcode(
|
||||||
|
date: string | Date,
|
||||||
|
headcode: string
|
||||||
|
): Promise<TrainServices[]> {
|
||||||
const sanitizedHeadcode = clean.removeNonAlphanumeric(headcode).toUpperCase();
|
const sanitizedHeadcode = clean.removeNonAlphanumeric(headcode).toUpperCase();
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`trainServiceServices.findByHeadcode: Searching for headcode ${sanitizedHeadcode}`
|
`trainServiceServices.findByHeadcode: Searching for headcode ${sanitizedHeadcode}`
|
||||||
@ -88,7 +91,10 @@ async function findByHeadcode(date: string | Date, headcode: string): Promise<Tr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finds a train by its trainUid value
|
// Finds a train by its trainUid value
|
||||||
async function findByTrainUid(uid: string, date: Date | string = new Date()): Promise<TrainServices | null> {
|
async function findByTrainUid(
|
||||||
|
uid: string,
|
||||||
|
date: Date | string = new Date()
|
||||||
|
): Promise<TrainServices | null> {
|
||||||
let queryDate;
|
let queryDate;
|
||||||
if (date === "now") {
|
if (date === "now") {
|
||||||
queryDate = new Date();
|
queryDate = new Date();
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
} from "../utils/pis.utils";
|
} from "../utils/pis.utils";
|
||||||
import { Document } from "mongodb";
|
import { Document } from "mongodb";
|
||||||
|
|
||||||
const supported = ["GW", "UK"];
|
export const supported = ["GW", "UK"];
|
||||||
|
|
||||||
async function findPisByOrigDest(start: string, end: string) {
|
async function findPisByOrigDest(start: string, end: string) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
|
@ -1,21 +1,36 @@
|
|||||||
import { logger } from "../utils/logger.utils";
|
import { logger } from "../utils/logger.utils";
|
||||||
import { findByTiplocArray } from "../services/pis.services"
|
import { findByTiplocArray, supported } from "../services/pis.services";
|
||||||
import { queryAggregate } from "./dbAccess.services";
|
import { queryAggregate } from "./dbAccess.services";
|
||||||
import { getFindByHeadcodePipeline, getFindByTrainUidPipeline } from "../utils/trainService.utils"
|
import {
|
||||||
import { removeNonAlphanumeric } from "../utils/sanitizer.utils"
|
getFindByHeadcodePipeline,
|
||||||
|
getFindByTrainUidPipeline,
|
||||||
|
} from "../utils/trainService.utils";
|
||||||
|
import { removeNonAlphanumeric } from "../utils/sanitizer.utils";
|
||||||
|
import { formatTimetableDetail } from "../utils/processors/timetable/timetableProcessor.utils";
|
||||||
|
|
||||||
import type { TrainServices, Service, Stop, SimpleService } from "@owlboard/ts-types";
|
import type {
|
||||||
|
TrainServices,
|
||||||
|
Service,
|
||||||
|
Stop,
|
||||||
|
SimpleService,
|
||||||
|
OB_Pis_SimpleObject,
|
||||||
|
} from "@owlboard/ts-types";
|
||||||
|
|
||||||
export async function findByHeadcode(headcode: string, date: Date | string): Promise<SimpleService[]> {
|
export async function findByHeadcode(
|
||||||
|
headcode: string,
|
||||||
|
date: Date | string
|
||||||
|
): Promise<SimpleService[]> {
|
||||||
const sanitizedHeadcode = removeNonAlphanumeric(headcode);
|
const sanitizedHeadcode = removeNonAlphanumeric(headcode);
|
||||||
logger.debug(`trainServices.findByHeadcode: Searching for trains by headcode: ${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.
|
// 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);
|
const searchDate = date === "now" ? new Date() : new Date(date);
|
||||||
searchDate.setHours(12, 0, 0);
|
searchDate.setHours(12, 0, 0);
|
||||||
|
|
||||||
// Get the 'shortDay'
|
// Get the 'shortDay'
|
||||||
const shortDay = getShortDay(searchDate)
|
const shortDay = getShortDay(searchDate);
|
||||||
|
|
||||||
const query = {
|
const query = {
|
||||||
headcode: sanitizedHeadcode,
|
headcode: sanitizedHeadcode,
|
||||||
@ -23,16 +38,22 @@ export async function findByHeadcode(headcode: string, date: Date | string): Pro
|
|||||||
scheduleEndDate: { $gte: searchDate },
|
scheduleEndDate: { $gte: searchDate },
|
||||||
daysRun: { $in: [shortDay] },
|
daysRun: { $in: [shortDay] },
|
||||||
};
|
};
|
||||||
const pipeline = getFindByHeadcodePipeline(query)
|
const pipeline = getFindByHeadcodePipeline(query);
|
||||||
|
|
||||||
const result: SimpleService[] = await queryAggregate("timetable", pipeline) as SimpleService[]
|
const result: SimpleService[] = (await queryAggregate(
|
||||||
|
"timetable",
|
||||||
|
pipeline
|
||||||
|
)) as SimpleService[];
|
||||||
|
|
||||||
const services = filterServices(result);
|
const services = filterServices(result);
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function findByTrainUid(uid: string, date: Date | string = new Date()) {
|
export async function findByTrainUid(
|
||||||
|
uid: string,
|
||||||
|
date: Date | string = new Date()
|
||||||
|
) {
|
||||||
// Set the correct date - whether a date or "now" was passed to function
|
// Set the correct date - whether a date or "now" was passed to function
|
||||||
let queryDate: Date;
|
let queryDate: Date;
|
||||||
if (date instanceof Date) {
|
if (date instanceof Date) {
|
||||||
@ -46,41 +67,64 @@ export async function findByTrainUid(uid: string, date: Date | string = new Date
|
|||||||
trainUid: uid,
|
trainUid: uid,
|
||||||
scheduleStartDate: { $lte: queryDate },
|
scheduleStartDate: { $lte: queryDate },
|
||||||
scheduleEndDate: { $gte: queryDate },
|
scheduleEndDate: { $gte: queryDate },
|
||||||
daysRun: { $in: [getShortDay(queryDate)] }
|
daysRun: { $in: [getShortDay(queryDate)] },
|
||||||
|
};
|
||||||
|
const pipeline = getFindByTrainUidPipeline(query);
|
||||||
|
|
||||||
|
const result = (await queryAggregate("timetable", pipeline)) as Service[];
|
||||||
|
|
||||||
|
let services = filterServices(result) as Service[];
|
||||||
|
|
||||||
|
// Check if the operator is on the supported TOC list for PIS Codes - if so, call the fetchPisCode function.
|
||||||
|
let pis: OB_Pis_SimpleObject | null;
|
||||||
|
if (supported.includes(services[0]?.operator)) {
|
||||||
|
pis = await fetchPisCode(services[0]?.stops);
|
||||||
}
|
}
|
||||||
const pipeline = getFindByTrainUidPipeline(query)
|
// TODO: Format and return data, the function called is not yet complete
|
||||||
|
return formatTimetableDetail(services[0], pis)
|
||||||
const result = await queryAggregate("timetable", pipeline) as Service[]
|
|
||||||
|
|
||||||
let services = filterServices(result) as Service[]
|
|
||||||
|
|
||||||
// Next up is the public stops filter, the resulting array is used for a PIS search
|
|
||||||
// I can probably write a function that both builds the public stop array and returns
|
|
||||||
// a PIS object - or null.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal Functions:
|
// Internal Functions:
|
||||||
|
|
||||||
|
// Filters out non-passenger stops and then uses the stop array to request a PIS code for the service
|
||||||
|
async function fetchPisCode(
|
||||||
|
stops: Stop[]
|
||||||
|
): Promise<OB_Pis_SimpleObject | null> {
|
||||||
|
let tiplocList: string[] = [];
|
||||||
|
for (const stop in stops) {
|
||||||
|
if (stops[stop]["isPublic"]) tiplocList.push(stops[stop]["tiploc"]);
|
||||||
|
}
|
||||||
|
const pisData = await findByTiplocArray(tiplocList);
|
||||||
|
return pisData;
|
||||||
|
}
|
||||||
|
|
||||||
// Outputs the standard 'shortday' string from a Date.
|
// Outputs the standard 'shortday' string from a Date.
|
||||||
function getShortDay(day: Date): string {
|
function getShortDay(day: Date): string {
|
||||||
const dayMap = ["su", "m", "t", "w", "th", "f", "s"];
|
const dayMap = ["su", "m", "t", "w", "th", "f", "s"];
|
||||||
const shortDay = dayMap[day.getDay()];
|
const shortDay = dayMap[day.getDay()];
|
||||||
return shortDay
|
return shortDay;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filters services using their STP indicator so that over-riding entries are returned correctly
|
// Filters services using their STP indicator so that over-riding entries are returned correctly
|
||||||
function filterServices(services: SimpleService[]): (SimpleService[]) {
|
function filterServices(services: SimpleService[]): SimpleService[] {
|
||||||
let stpIndicators: Record<string, { hasC: boolean; hasN: boolean; hasO: boolean; hasP: boolean }> = {};
|
let stpIndicators: Record<
|
||||||
let filteredServices: SimpleService[] = []
|
string,
|
||||||
|
{ hasC: boolean; hasN: boolean; hasO: boolean; hasP: boolean }
|
||||||
|
> = {};
|
||||||
|
let filteredServices: SimpleService[] = [];
|
||||||
|
|
||||||
for (const service of services) {
|
for (const service of services) {
|
||||||
const trainUid = service["trainUid"], stpIndicator = service["stpIndicator"]
|
const trainUid = service["trainUid"],
|
||||||
|
stpIndicator = service["stpIndicator"];
|
||||||
|
|
||||||
// Creates the stpIndicators array:
|
// Creates the stpIndicators array:
|
||||||
if (!stpIndicators[trainUid]) {
|
if (!stpIndicators[trainUid]) {
|
||||||
stpIndicators[trainUid] = {
|
stpIndicators[trainUid] = {
|
||||||
hasC: false, hasN: false, hasO: false, hasP: false,
|
hasC: false,
|
||||||
}
|
hasN: false,
|
||||||
|
hasO: false,
|
||||||
|
hasP: false,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stpIndicator === "C") {
|
if (stpIndicator === "C") {
|
||||||
@ -100,7 +144,7 @@ function filterServices(services: SimpleService[]): (SimpleService[]) {
|
|||||||
// Iterate each service, and only output one service matching each trainUid,
|
// 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.
|
// C > N > O > P is the order, with C being prioritised over other STP types.
|
||||||
for (const service of services) {
|
for (const service of services) {
|
||||||
const trainUid = service["trainUid"]
|
const trainUid = service["trainUid"];
|
||||||
const thisStpIndicators = stpIndicators[trainUid];
|
const thisStpIndicators = stpIndicators[trainUid];
|
||||||
const stpIndicator = service["stpIndicator"];
|
const stpIndicator = service["stpIndicator"];
|
||||||
|
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
import type {Service, OB_TrainTT_service, OB_Pis_SimpleObject, OB_TrainTT_stopDetail, Stop} from "@owlboard/ts-types"
|
||||||
|
|
||||||
|
export function formatTimetableDetail(service: Service, pis: OB_Pis_SimpleObject | null): OB_TrainTT_service {
|
||||||
|
const formattedService: OB_TrainTT_service = {
|
||||||
|
stpIndicator: service.stpIndicator,
|
||||||
|
operator: service.operator,
|
||||||
|
trainUid: service.trainUid,
|
||||||
|
headcode: service.headcode,
|
||||||
|
powerType: service.powerType,
|
||||||
|
planSpeed: convertStringToNumber(service.planSpeed), // Force convert from string to number.
|
||||||
|
scheduleStart: service.scheduleStartDate,
|
||||||
|
scheduleEnd: service.scheduleEndDate,
|
||||||
|
daysRun: service.daysRun,
|
||||||
|
stops: service.stops, // Need separate function to ensure type compatibility
|
||||||
|
vstp: service.vstp, // Need to ensure that ts-types is up to date.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pis) {
|
||||||
|
formattedService.pis = pis;
|
||||||
|
}
|
||||||
|
|
||||||
|
return formattedService
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatStops(stops: Stop[]): OB_TrainTT_stopDetail[] {
|
||||||
|
// Cleanly coerce Stop[] to OB_TrainTT_stopDetail[]
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertStringToNumber(str: string): number {
|
||||||
|
const number = parseFloat(str)
|
||||||
|
if (isNaN(number)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return number
|
||||||
|
}
|
||||||
|
}
|
@ -20,7 +20,10 @@ export function getFindByHeadcodePipeline(query: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getFindByTrainUidPipeline(query: any) {
|
export function getFindByTrainUidPipeline(query: any) {
|
||||||
return [{
|
return [
|
||||||
'$match': query,
|
{
|
||||||
},{'$project': {'_id': 0}}]
|
$match: query,
|
||||||
|
},
|
||||||
|
{ $project: { _id: 0 } },
|
||||||
|
];
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user