import type { trainDataType } from "@/lib/trainPositionTextArray"; import { officialPositionLookupKey, type OfficialPositionLookupInput, } from "@/lib/domain/railway"; const toLookupInput = ( train: trainDataType, ): OfficialPositionLookupInput | null => { if ( typeof train.Pos !== "string" || train.Pos.length === 0 || typeof train.Line !== "string" || train.Line.length === 0 || train.PosNum === undefined || (typeof train.PosNum === "string" && train.PosNum.length === 0) || (typeof train.PosNum === "number" && !Number.isFinite(train.PosNum)) ) { return null; } return { line: train.Line, pos: train.Pos, posNum: train.PosNum, }; }; /** * Keeps the currently displayed official metadata while the next current-train * snapshot is being enriched. Only an identical line/position/position-number * tuple may carry metadata forward. */ export const carryForwardOfficialPositionMetadata = ( next: readonly trainDataType[], previous: readonly trainDataType[], ): trainDataType[] => { const metadataByKey = new Map< string, NonNullable >(); for (const train of previous) { if (!train.officialPosition) continue; const input = toLookupInput(train); if (!input) continue; metadataByKey.set( officialPositionLookupKey(input), train.officialPosition, ); } return next.map((train) => { if (train.officialPosition) return train; const input = toLookupInput(train); if (!input) return train; const metadata = metadataByKey.get(officialPositionLookupKey(input)); return metadata ? { ...train, officialPosition: metadata } : train; }); };