Files
jrshikoku/lib/currentTrainMetadata.ts
harukin-expo-dev-env 1ecd026908 feat: Implement official position metadata handling and caching
- Add `currentTrainMetadata.ts` to manage carrying forward official position metadata between train snapshots.
- Introduce `lineDisplayName.ts` for mapping line IDs to display names.
- Create `officialPositionCache.ts` for parsing and serializing official position data with cache validation.
- Enhance `officialPositionService.ts` to support persistent caching of official positions and improve resolver functionality.
- Update `requestCoordinator.ts` to allow cancellation of polling requests without disposing of the coordinator.
- Modify `trainTimeFiltering.ts` to incorporate line ID context when checking for duplicate train data.
- Refactor `useCurrentTrain.tsx` to support polling for current train data with official position enrichment.
- Add tests for new features, including persistent cache behavior and handling of ambiguous train data.
2026-09-15 13:48:21 +09:00

60 lines
1.7 KiB
TypeScript

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<trainDataType["officialPosition"]>
>();
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;
});
};