// This code is mostly from marudor's great bahn.expert project. // See here: https://github.com/marudor/bahn.expert/tree/main/src/server/coachSequence // Since the source is MIT licensed, to following code is it too. // import { enrichCoachSequence } from './commonMapping.js'; import { getLineFromNumber } from './lineNumberMapping.js'; const mapSectors = (sectors, basePercent) => sectors?.map((s) => ({ name: s.name, position: { startPercent: basePercent * s.start, endPercent: basePercent * s.end, }, }) || []); const mapStop = (evaNumber, platform) => { if (platform?.start === undefined || platform.end === undefined) { return [undefined, 0]; } const basePercent = 100 / (platform.end - platform.start); return [ { stopPlace: { evaNumber, name: '', }, sectors: mapSectors(platform.sectors, basePercent), }, basePercent, ]; }; const mapClass = (vehicleType) => { switch (vehicleType.category) { case 'LOCOMOTIVE': case 'POWERCAR': return 4; case 'DININGCAR': return 2; } if (vehicleType.hasFirstClass && vehicleType.hasEconomyClass) return 3; if (vehicleType.hasFirstClass) return 1; if (vehicleType.hasEconomyClass) return 2; return 0; } const diningCategories = new Set([ 'DININGCAR', 'HALFDININGCAR_ECONOMY_CLASS', 'HALFDININGCAR_FIRST_CLASS', ]); const mapFeatures = (vehicle) => { const features = {}; for (const a of vehicle.amenities) { switch (a.type) { case 'BIKE_SPACE': { features.bike = true; break; } case 'BISTRO': { features.dining = true; break; } case 'INFO': { features.info = true; break; } case 'SEATS_BAHN_COMFORT': { features.comfort = true; break; } case 'SEATS_SEVERELY_DISABLED': { features.disabled = true; break; } case 'WHEELCHAIR_SPACE': { features.wheelchair = true; break; } case 'WIFI': { features.wifi = true; break; } case 'ZONE_FAMILY': { features.family = true; break; } case 'ZONE_QUIET': { features.quiet = true; break; } case 'CABIN_INFANT': { features.toddler = true; break; } } } if (!features.dining && diningCategories.has(vehicle.type.category)) { features.dining = true; } return features; } const mapVehicle = (vehicle, basePercent) => { if (!vehicle.platformPosition) return undefined; return { identificationNumber: vehicle.wagonIdentificationNumber?.toString(), uic: vehicle.vehicleID, type: vehicle.type.constructionType, class: mapClass(vehicle.type), vehicleCategory: vehicle.type.category, closed: vehicle.status === 'CLOSED' || vehicle.type.category === 'LOCOMOTIVE' || vehicle.type.category === 'POWERCAR', position: { startPercent: basePercent * vehicle.platformPosition.start, endPercent: basePercent * vehicle.platformPosition.end, }, features: mapFeatures(vehicle), }; } const mapGroup = (group, basePercent) => { const coaches = group.vehicles.map(vehicle => mapVehicle(vehicle, basePercent)); if (coaches.includes(undefined)) return undefined; return { name: group.name, destinationName: group.transport.destination.name, originName: 'UNKNOWN', number: group.transport.number.toString(), coaches: coaches, }; } const mapDirection = coaches => { const first = coaches[0]; const last = coaches.at(-1); return last.position.startPercent > first.position.startPercent; } const mapSequence = async (sequence, basePercent) => { const groups = await Promise.all( sequence.groups.map((g) => mapGroup(g, basePercent)), ); if (groups.includes(undefined)) return undefined; return { groups: groups, }; } export const mapInformation = async (upstreamSequence, trainCategory, trainNumber, evaNumber) => { if (!upstreamSequence) return undefined; const [stop, basePercent] = mapStop(evaNumber, upstreamSequence.platform); if (!stop) return undefined; const sequence = await mapSequence(upstreamSequence, basePercent); if (!sequence) return undefined; const allCoaches = sequence.groups.flatMap((g) => g.coaches); const information = { source: 'DB-bahnde', product: { number: trainNumber, type: trainCategory, }, isRealtime: allCoaches.every( (c) => c.uic || c.vehicleCategory === 'LOCOMOTIVE', ), stop, sequence, direction: mapDirection(allCoaches), journeyId: upstreamSequence.journeyID, }; enrichCoachSequence(information); return information; };