Skip to content

Commit

Permalink
Bugfixes for GTFS-RT Infoplus feed
Browse files Browse the repository at this point in the history
  • Loading branch information
Arilith committed Nov 25, 2024
1 parent a13ff4f commit 6e28a0f
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 104 deletions.
2 changes: 1 addition & 1 deletion src/Database/Database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const Knex = knex({
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
port: 5432
port: process.env.DB_PORT ? parseInt(process.env.DB_PORT) : 5432
},
pool: {
min: 0,
Expand Down
1 change: 1 addition & 0 deletions src/Interfaces/DatabaseRitInfoUpdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ export interface IRitInfoStopUpdate extends IDatabaseStopUpdate {
plannedTrack: string | null;
actualTrack: string | null;
stationCode: string;
name: string;
}
29 changes: 27 additions & 2 deletions src/Models/RitInfoUpdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
* Questions? Email: [email protected]
*/

import {IDatabaseRitInfoUpdate} from '../Interfaces/DatabaseRitInfoUpdate'
import {IDatabaseRitInfoUpdate, IRitInfoStopUpdate} from '../Interfaces/DatabaseRitInfoUpdate'
import {ExtendedStopTimeUpdate} from "./GTFS/StopTimeUpdate";
import {RitInfoStopUpdate} from "./StopUpdates/RitinfoStopUpdate";
import {StopUpdateCollection} from "./StopUpdateCollection";
import {InternationalAgencys, InternationalTrainSeries} from '../Utilities/InternationalAgencys';
import {IJourneyChange} from "../Shared/src/Types/Infoplus/V2/JourneyChange";
import {LogicalJourneyChangeType} from "../Shared/src/Types/Infoplus/V2/Changes/LogicalJourneyChangeType";
import {TrainType} from "../Shared/src/Types/API/V2/InfoPlus/TrainType";

export class RitInfoUpdate {
private readonly _agency: string;
Expand Down Expand Up @@ -50,12 +51,36 @@ export class RitInfoUpdate {
this._timestamp = update.timestamp;

this._routeType = update.routeType;
this._routeLongName = update.routeLongName;
this._routeLongName = this.getRouteLongName(update);
this._agencyId = update.agencyId;

this._isInternationalTrain = this.setInternationalTrain();
}

private getRouteLongName(update: IDatabaseRitInfoUpdate): string {
if(update.routeLongName)
return update.routeLongName;

const firstStop = this.stops.first();
const lastStop = this.stops.last();

//The trainseries of e.g. 1234 is 1200, 570 is 500, 29290 is 29000
const trainSeries = update.trainNumber - (update.trainNumber % 100);
const trainType = update.trainType;
const longTrainType = TrainType.shortToLong(TrainType.fromStringToShort(trainType));

//Haarlem <-> Amsterdam Sloterdijk BST26000
//Nachtnettrein Amsterdam Bijlmer ArenA <-> Leiden Centraal

//Rotterdam Centraal <-> Amsterdam Centraal ICD1100
if(firstStop.name && lastStop.name) {
return `${firstStop.name} <-> ${lastStop.name} ${trainType}${trainSeries}`;
}

return `${longTrainType} ${trainSeries}`;

}

private setInternationalTrain(): boolean {
let isInternationalTrain = false;

Expand Down
20 changes: 19 additions & 1 deletion src/Models/StopUpdateCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ export class StopUpdateCollection extends Collection<RitInfoStopUpdate> {

//Make sure all times are increasing
this.checkIncreasingTimes();

/*
@InfoPlaza - Specific to Infoplaza IFF GTFS
Set all stop sequences sequentually irrespective of the sequence in InfoPlus
*/
this.setSequenceNumbers();
}

private setFirstStop() {
Expand Down Expand Up @@ -101,6 +107,18 @@ export class StopUpdateCollection extends Collection<RitInfoStopUpdate> {
}
}

/**
* Set the sequence number of each stop to its index in the array + 1
* @private
*/
private setSequenceNumbers() {
for (let i = 0; i < this.length; i++) {
const stop = this.get(i);
stop.sequence = i + 1;
this.set(i, stop);
}
}

/**
* Fix the current stop time by setting the arrival time to the planned arrival time + min(delay at previous stop, delay at next stop)
* @param previousStop The previous stop in the sequence
Expand Down Expand Up @@ -136,7 +154,7 @@ export class StopUpdateCollection extends Collection<RitInfoStopUpdate> {
if (stopToFix.plannedArrivalTime === null) return;

// Calculate the new arrival time by adding the departure delay at the previous stop to the planned arrival time at the current stop
const newArrivalTime = stopToFix.plannedArrivalTime.getTime() + previousStop.departureDelay;
const newArrivalTime = (stopToFix.plannedArrivalTime.getTime() / 1000) + previousStop.departureDelay;

// If the new arrival time is not increasing, we can't fix the arrival time
if (newArrivalTime < previousStop.departureTime) {
Expand Down
5 changes: 5 additions & 0 deletions src/Models/StopUpdates/RitinfoStopUpdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export class RitInfoStopUpdate extends StopUpdate {

public readonly stationCode: string;

public readonly name: string;

constructor(update: IRitInfoStopUpdate) {
super(update);

Expand All @@ -40,6 +42,9 @@ export class RitInfoStopUpdate extends StopUpdate {
this.platform = update.platform;
this.track = update.track;


this.name = update.name;

if(this.platform !== this.track)
console.log(`[RitInfoStopUpdate] Platform and Track are not the same for stop ${this.stationCode}! Platform: ${this.platform}, Track: ${this.track}`)
}
Expand Down
192 changes: 92 additions & 100 deletions src/Repositories/InfoplusRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,114 +15,106 @@ export class InfoplusRepository extends Repository implements IInfoPlusRepositor
console.time('getCurrentRealtimeTripUpdates');
return this.database.raw(`
WITH cal_dates AS (SELECT DISTINCT "serviceId", "date"
FROM "StaticData-NL".calendar_dates
WHERE "date" >= ?::date
AND date <= ?::date),
trips AS (SELECT "tripId", "routeId", "directionId", "tripShortName", "shapeId", "serviceId"
FROM "StaticData-NL".trips
WHERE agency = 'IFF'
AND "serviceId" IN (SELECT DISTINCT "serviceId"
FROM cal_dates)),
stops AS (SELECT "stopId", "stationCode", "platformCode"
FROM "StaticData-NL".stops
WHERE "stationCode" IS NOT NULL)
SELECT jpjl."journeyPartNumber" AS "trainNumber",
jpjl."shortJourneyPartNumber" AS "shortTrainNumber",
r."trainType"->>'code' AS "trainType",
r.agency,
r."operationDate",
r."showsInTravelPlanner" AS "showsInTripPlanner",
r."timestamp",
coalesce(lj."journeyChanges", jpjl."journeyPartChanges") AS "changes",
t."tripId" AS "tripId",
coalesce(t."routeId", t_short."routeId") AS "routeId",
rt."routeType" AS "routeType",
rt."agencyId" AS "agencyId",
rt."routeLongName" AS "routeLongName",
coalesce(t."directionId", t_short."directionId") AS "directionId",
coalesce(t."shapeId", t_short."shapeId") AS "shapeId",
jsonb_agg(
jsonb_build_object(
'stationCode',
si."stationCode",
'plannedWillStop',
si."plannedWillStop",
'actualWillStop',
si."actualWillStop",
'plannedArrivalTime',
si."plannedArrivalTime",
'plannedDepartureTime',
si."plannedDepartureTime",
'departureTime',
coalesce(si."actualDepartureTime", si."plannedDepartureTime"),
'arrivalTime',
coalesce(si."actualArrivalTime", si."plannedArrivalTime"),
'departureDelay',
si."actualDepartureTime" - si."plannedDepartureTime",
'arrivalDelay',
si."actualArrivalTime" - si."plannedArrivalTime",
'changes',
si.changes,
'stopId',
COALESCE(s."stopId", lateral_stop."stopId", si."stationCode"),
'platform',
s."platformCode",
'plannedTrack',
coalesce(si."plannedArrivalTracks", si."plannedDepartureTracks"),
'actualTrack',
coalesce(si."actualArrivalTracks", si."actualDepartureTracks"),
'track',
coalesce(si."actualArrivalTracks", si."actualDepartureTracks", si."plannedArrivalTracks",
si."plannedDepartureTracks"),
'sequence',
si."stopOrder"
) ORDER BY si."stopOrder") stops
FROM "InfoPlus-new".ritinfo r
JOIN "InfoPlus-new".logical_journeys lj
ON r."trainNumber" = lj."trainNumber" AND r."operationDate" = lj."operationDate"
JOIN "InfoPlus-new".logical_journey_parts jpjl
ON lj."journeyNumber" = jpjl."journeyNumber" AND
r."operationDate" = jpjl."operationDate"
JOIN "InfoPlus-new".stop_information si
ON jpjl."journeyPartNumber" = si."journeyPartNumber" AND
jpjl."operationDate" = si."operationDate" AND
("plannedWillStop" = true OR "actualWillStop" = true) AND
(coalesce("plannedDepartureTime", "actualArrivalTime") IS NOT NULL OR
coalesce("plannedArrivalTime", "actualArrivalTime") IS NOT NULL)
LEFT JOIN trips t
ON jpjl."journeyPartNumber" = t."tripShortName"::int
FROM "StaticData-NL".calendar_dates
WHERE "date" >= ?::date
AND date <= ?::date),
trips AS (SELECT "tripId", "routeId", "directionId", "tripShortName", "shapeId", "serviceId"
FROM "StaticData-NL".trips
WHERE agency = 'IFF'
AND "serviceId" IN (SELECT DISTINCT "serviceId"
FROM cal_dates)),
stops AS (SELECT "stopId", "stationCode", "platformCode", "stopName"
FROM "StaticData-NL".stops
WHERE "stationCode" IS NOT NULL)
SELECT jpjl."journeyPartNumber" AS "trainNumber",
jpjl."shortJourneyPartNumber" AS "shortTrainNumber",
r."trainType" ->> 'code' AS "trainType",
r.agency,
r."operationDate",
r."showsInTravelPlanner" AS "showsInTripPlanner",
r."timestamp",
coalesce(lj."journeyChanges", jpjl."journeyPartChanges") AS "changes",
t."tripId" AS "tripId",
coalesce(t."routeId", t_short."routeId") AS "routeId",
rt."routeType" AS "routeType",
rt."agencyId" AS "agencyId",
rt."routeLongName" AS "routeLongName",
coalesce(t."directionId", t_short."directionId") AS "directionId",
coalesce(t."shapeId", t_short."shapeId") AS "shapeId",
jsonb_agg(
CASE
WHEN s."stopId" IS NOT NULL OR lateral_stop."stopId" IS NOT NULL THEN
jsonb_build_object(
'stationCode', si."stationCode",
'plannedWillStop', si."plannedWillStop",
'actualWillStop', si."actualWillStop",
'plannedArrivalTime', si."plannedArrivalTime",
'plannedDepartureTime', si."plannedDepartureTime",
'departureTime', coalesce(si."actualDepartureTime", si."plannedDepartureTime"),
'arrivalTime', coalesce(si."actualArrivalTime", si."plannedArrivalTime"),
'departureDelay', si."actualDepartureTime" - si."plannedDepartureTime",
'arrivalDelay', si."actualArrivalTime" - si."plannedArrivalTime",
'changes', si.changes,
'stopId', COALESCE(s."stopId", lateral_stop."stopId"),
'platform', s."platformCode",
'plannedTrack', coalesce(si."plannedArrivalTracks", si."plannedDepartureTracks"),
'actualTrack', coalesce(si."actualArrivalTracks", si."actualDepartureTracks"),
'track',
coalesce(si."actualArrivalTracks", si."actualDepartureTracks", si."plannedArrivalTracks",
si."plannedDepartureTracks"),
'sequence', si."stopOrder",
'name', COALESCE(s."stopName", lateral_stop."stopName", si."stationCode")
)
END
ORDER BY si."stopOrder"
) FILTER (WHERE s."stopId" IS NOT NULL OR lateral_stop."stopId" IS NOT NULL) AS stops
FROM "InfoPlus-new".ritinfo r
JOIN "InfoPlus-new".logical_journeys lj
ON r."trainNumber" = lj."trainNumber" AND r."operationDate" = lj."operationDate"
JOIN "InfoPlus-new".logical_journey_parts jpjl
ON lj."journeyNumber" = jpjl."journeyNumber" AND
r."operationDate" = jpjl."operationDate"
JOIN "InfoPlus-new".stop_information si
ON jpjl."journeyPartNumber" = si."journeyPartNumber" AND
jpjl."operationDate" = si."operationDate" AND
("plannedWillStop" = true OR "actualWillStop" = true) AND
(coalesce("plannedDepartureTime", "actualArrivalTime") IS NOT NULL OR
coalesce("plannedArrivalTime", "actualArrivalTime") IS NOT NULL)
LEFT JOIN trips t
ON jpjl."journeyPartNumber" = t."tripShortName"::int
AND EXISTS (SELECT 1
FROM cal_dates cd
WHERE cd."serviceId" = t."serviceId"
AND cd."date" = r."operationDate")
LEFT JOIN trips t_short ON t."tripId" IS NULL AND jpjl."shortJourneyPartNumber" = t_short."tripShortName"::int
AND EXISTS (SELECT 1
AND EXISTS (SELECT 1
FROM cal_dates cd
WHERE cd."serviceId" = t_short."serviceId"
AND cd."date" = r."operationDate")
LEFT JOIN stops s ON (s."stationCode" = lower(si."stationCode") AND
s."platformCode" =
coalesce(si."actualArrivalTracks", si."actualDepartureTracks", si."plannedArrivalTracks",
si."plannedDepartureTracks"))
LEFT JOIN LATERAL (
SELECT "stopId"
FROM stops lax
WHERE lax."stationCode" = lower(si."stationCode")
LIMIT 1
) AS lateral_stop ON s."stopId" IS NULL
LEFT JOIN "StaticData-NL".routes rt ON rt."routeId" = coalesce(t."routeId", t_short."routeId")
WHERE r."operationDate" >= ?::date
AND NOT (
r."operationDate" > ?::date
AND lj."journeyChanges" IS NULL
)
GROUP BY r."trainNumber", jpjl."journeyPartNumber", r."shortTrainNumber", jpjl."shortJourneyPartNumber",
r."trainType", r.agency,
r."showsInTravelPlanner", r.timestamp, r."operationDate", t."tripId", coalesce(t."tripId", t_short."tripId"),
coalesce(lj."journeyChanges", jpjl."journeyPartChanges"),
t."tripId", coalesce(t."routeId", t_short."routeId"),
coalesce(t."directionId", t_short."directionId"), coalesce(t."shapeId", t_short."shapeId"), rt."routeType", rt."agencyId", rt."routeLongName";
AND cd."date" = r."operationDate")
LEFT JOIN stops s ON (s."stationCode" = lower(si."stationCode") AND
s."platformCode" =
coalesce(si."actualArrivalTracks", si."actualDepartureTracks", si."plannedArrivalTracks",
si."plannedDepartureTracks"))
LEFT JOIN LATERAL (
SELECT "stopId", "stopName"
FROM stops lax
WHERE lax."stationCode" = lower(si."stationCode")
LIMIT 1
) AS lateral_stop ON s."stopId" IS NULL
LEFT JOIN "StaticData-NL".routes rt ON rt."routeId" = coalesce(t."routeId", t_short."routeId")
WHERE r."operationDate" >= ?::date
AND NOT (
r."operationDate" > ?::date
AND lj."journeyChanges" IS NULL
)
GROUP BY r."trainNumber", jpjl."journeyPartNumber", r."shortTrainNumber", jpjl."shortJourneyPartNumber",
r."trainType", r.agency,
r."showsInTravelPlanner", r.timestamp, r."operationDate", t."tripId", coalesce(t."tripId", t_short."tripId"),
coalesce(lj."journeyChanges", jpjl."journeyPartChanges"),
t."tripId", coalesce(t."routeId", t_short."routeId"),
coalesce(t."directionId", t_short."directionId"), coalesce(t."shapeId", t_short."shapeId"), rt."routeType",
rt."agencyId", rt."routeLongName";
`, [operationDateOfTodayOrYesterday, endOperationDate, operationDateOfTodayOrYesterday, operationDateOfTodayOrTomorrow]).then(result => {
console.timeEnd('getCurrentRealtimeTripUpdates');
return result.rows;
Expand Down

0 comments on commit 6e28a0f

Please sign in to comment.