Skip to content

Commit

Permalink
backend: add SequenceController
Browse files Browse the repository at this point in the history
- fetches the coach sequence of a connection
  • Loading branch information
schmolldechse committed Feb 15, 2025
1 parent 5ba5e11 commit 5b9f323
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 1 deletion.
50 changes: 50 additions & 0 deletions backend/controllers/journey/SequenceController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Controller, Get, Queries, Res, Route, Tags, type TsoaResponse } from "tsoa";
import { DateTime } from "luxon";
import { mapCoachSequence } from "../../lib/mapping.ts";

class SequenceQuery {
lineDetails!: string;
evaNumber!: string;
date!: string;
}

@Route("journey/sequence")
@Tags("Coach Sequences")
export class SequenceController extends Controller {
@Get()
async getSequenceById(
@Queries() query: SequenceQuery,
@Res() badRequestResponse: TsoaResponse<400, { reason: string }>
): Promise<any> {
if (query.lineDetails === "") {
return badRequestResponse(400, { reason: "lineDetails must not be empty" });
}
if (!/^\d+$/.test(query.evaNumber)) {
return badRequestResponse(400, { reason: "evaNumber is not an integer" });
}

const dateValidation = DateTime.fromFormat(query.date, "yyyyMMdd");
if (!dateValidation.isValid) {
return badRequestResponse(400, { reason: `${dateValidation.invalidExplanation}` });
}

return fetchCoachSequence(query);
}
}

const fetchCoachSequence = async (query: SequenceQuery): Promise<any> => {
const request = await fetch(`https://app.vendo.noncd.db.de/mob/zuglaeufe/${query.lineDetails}/halte/by-abfahrt/${query.evaNumber}_${query.date}/wagenreihung`, {
method: "GET",
headers: {
Accept: "application/x.db.vendo.mob.wagenreihung.v3+json",
"Content-Type": "application/x.db.vendo.mob.wagenreihung.v3+json",
"X-Correlation-ID": crypto.randomUUID() + "_" + crypto.randomUUID()
}
});

if (!request.ok) {
throw new Error("Failed to fetch coach sequence");
}

return mapCoachSequence(await request.json());
};
53 changes: 52 additions & 1 deletion backend/lib/mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { DateTime } from "luxon";
import type { Stop } from "../models/station.ts";
import type { Message } from "../models/message.ts";
import { mapToProduct } from "../models/products.ts";
import type { Sequence } from "../models/sequence.ts";

const mapConnection = (entry: any, type: "departures" | "arrivals", profile: "db" | "dbnav"): Connection => {
const delay: number = calculateDuration(
Expand Down Expand Up @@ -96,4 +97,54 @@ const mapMessages = (
};
};

export { mapConnection };
const mapCoachSequence = (entry: any): Sequence => {
return {
track: {
start: { position: entry?.gleis?.start?.position },
end: { position: entry?.gleis?.ende?.position },
sections: entry?.gleis?.sektoren?.map((rawSection: any) => ({
name: rawSection?.bezeichnung,
start: { position: rawSection?.start?.position },
end: { position: rawSection?.ende?.position },
gleisabschnittswuerfelPosition: rawSection?.gleisabschnittswuerfelPosition,
firstClass: rawSection?.ersteKlasse
})),
name: entry?.gleis?.bezeichnung
},
vehicleGroup: entry?.fahrzeuggruppen?.map((rawGroup: any) => ({
vehicles: rawGroup?.fahrzeuge?.map((rawVehicle: any) => ({
vehicleType: {
category: rawVehicle?.fahrzeugtyp?.fahrzeugkategorie,
model: rawVehicle?.fahrzeugtyp?.baureihe,
firstClass: rawVehicle?.fahrzeugtyp?.ersteKlasse,
secondClass: rawVehicle?.fahrzeugtyp?.zweiteKlasse
},
status: rawVehicle?.status,
orientation: rawVehicle?.orientierung,
positionOnTrack: {
start: { position: rawVehicle?.positionAmGleis?.start?.position },
end: { position: rawVehicle?.positionAmGleis?.ende?.position },
section: rawVehicle?.positionAmGleis?.sektor
},
equipment: rawVehicle?.ausstattungsmerkmale?.map((rawEquipment: any) => ({
type: rawEquipment?.art,
status: rawEquipment?.status
})),
orderNumber: rawVehicle?.ordnungsnummer
})),
tripReference: {
type: rawGroup?.fahrtreferenz?.typ,
line: rawGroup?.fahrtreferenz?.linie,
destination: { name: rawGroup?.fahrtreferenz?.ziel.bezeichnung },
category: rawGroup?.fahrtreferenz?.gattung,
fahrtNr: rawGroup?.fahrtreferenz?.fahrtnummer
},
designation: rawGroup?.bezeichnung
})),
direction: entry?.fahrtrichtung === "RECHTS" ? "RIGHT" : "LEFT",
plannedTrack: entry?.gleisSoll,
actualTrack: entry?.gleisVorschau
}
}

export { mapConnection, mapCoachSequence };
75 changes: 75 additions & 0 deletions backend/models/sequence.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
export interface Sequence {
track: Track;
vehicleGroup?: VehicleGroup[];
direction?: "RIGHT" | "LEFT";
plannedTrack?: string;
actualTrack?: string;
}

export interface Track {
start: { position: number };
end: { position: number };
sections: Section[] | [];
name: string; // name of the track
}

export interface Section {
name: string;
start: { position: number };
end: { position: number };
gleisabschnittswuerfelPosition: number; // ??????????????????????
firstClass: boolean;
}

export interface VehicleGroup {
vehicles: Vehicle[];
tripReference: TripReference;
designation: string;
}

export interface TripReference {
type: string;
line: string;
destination: { name: string; };
category: string;
fahrtNr: string;
}

export interface Vehicle {
vehicleType: VehicleType;
status: string;
orientation: string;
positionOnTrack: PositionOnTrack;
equipment: Equipment[];
orderNumber?: number; // ??
}

export interface VehicleType {
category: string;
model: string;
firstClass: boolean;
secondClass: boolean;
}

export interface PositionOnTrack {
start: { position: number };
end: { position: number };
section: string;
}

/**
* SEATS_SEVERELY_DISABLED
* ZONE_FAMILY
* ZONE_QUIET
* INFO
* CABIN_INFANT
* AIR_CONDITION
* TOILET_WHEELCHAIR
* WHEELCHAIR_SPACE
* SEATS_BAHN_COMFORT
* BIKE_SPACE
*/
export interface Equipment {
type: string;
status: string;
}

0 comments on commit 5b9f323

Please sign in to comment.