import { MapData, StationOnMap } from "@mt/components"; import { TEMP_STATION_TYPE_MAP } from "@mt/common-types"; import { Coordinates, Route, RouteStation, Station, Track, TransferStation, } from "@mt/common-types"; export function mapRouteFromApi( routeData: Route, stations: Station[] ): MapData { const { generalInfo, attractionGroupings, stations: routeStations, } = routeData; const { rotate, scale1, scale2, centerCoordinates, track } = generalInfo; return { mapRotateAngle: rotate, fullMapScale: scale1, zoomedMapScale: scale2, centerOfMapPoint: centerCoordinates, trackPoints: track, stationsOnMap: mapStationsFromApi(routeStations, stations, track), touristAttractionGroupsOnMap: attractionGroupings .filter(({ coordinates }) => Boolean(coordinates)) .map(({ iconSize, coordinates, attractionIds }) => ({ iconSize, pointOnMap: coordinates, touristAttractionsOnMap: attractionIds.map((id) => ({ id, pointOnMap: coordinates, })), })), }; } function mapStationsFromApi( routeStations: RouteStation[], stations: Station[], track: Track ): MapData["stationsOnMap"] { const stationsMap = new Map(stations.map((station) => [station.id, station])); const unionStations: Array & Station> = routeStations.map(({ stationId, ...station }) => ({ ...station, ...stationsMap.get(stationId), })); const mappedStations = unionStations.map((station) => { const { id, name, shortName, coordinates, textAlignment, mapOffsets, stationTypeId, transferStations, iconUrl, } = station; return { id, name, shortName, coordinates, transferStationInfos: mapTransfersToMap(transferStations, stationsMap), labelAlignment: textAlignment, labelOffset: mapOffsets, iconUrl, stationTypeId, }; }); const stationsOnMap = mappedStations.map((station) => { const { coordinates } = station; const trackIndex = track.findIndex( (trackPoint) => coordinates.lat === trackPoint.lat && coordinates.lon === trackPoint.lon ); return { ...station, pointOnMap: { ...coordinates, trackIndex, }, }; }) as MapData["stationsOnMap"]; return sortStationsByTrackOrder(track, stationsOnMap); } function sortStationsByTrackOrder( track: Track, stations: StationOnMap[] ): StationOnMap[] { // Create a map to store the index of each coordinate in the second array const coordinateIndexMap = new Map(); track.forEach((coordinate, index) => { coordinateIndexMap.set(getCoordinateString(coordinate), index); }); // Sort the first array based on the order of coordinates in the second array return [...stations].sort((a, b) => { const indexA = coordinateIndexMap.get(getCoordinateString(a.coordinates)) || 0; const indexB = coordinateIndexMap.get(getCoordinateString(b.coordinates)) || 0; return indexA - indexB; }); } // TODO: move to shared utils and refactor across the project function getCoordinateString(coordinate: Coordinates): string { return `${coordinate.lat}:${coordinate.lon}`; } function mapTransfersToMap( transferStations: TransferStation[], stationsMap: Map ) { return transferStations .filter(({ isShowOnMap }) => isShowOnMap) .sort(({ ordinal: ordinalA }, { ordinal: ordinalB }) => ordinalA - ordinalB) .map(({ stationId }) => { const { stationTypeId, shortName } = stationsMap.get(stationId); return { type: TEMP_STATION_TYPE_MAP[stationTypeId].type, name: shortName, }; }); }