diff --git a/src/components/route-board/RouteTerminus.tsx b/src/components/route-board/RouteTerminus.tsx index 0017e659dfa5..d9d068d1d8ab 100644 --- a/src/components/route-board/RouteTerminus.tsx +++ b/src/components/route-board/RouteTerminus.tsx @@ -1,21 +1,104 @@ +import React, { useContext, useMemo } from "react"; import { useTranslation } from "react-i18next"; import { Box, SxProps, Theme, Typography } from "@mui/material"; import { toProperCase } from "../../utils"; +import AppContext from "../../AppContext"; const RouteTerminus = ({ terminus }) => { const { t, i18n } = useTranslation(); + const { + db: { routeList, stopList } + } = useContext(AppContext); + const { bound, route, stops, co, gtfsId, dest, orig } = terminus; + + const firstLastDiff = (arr) => { + if (arr.length < 2) return arr; + return [arr[0], arr[arr.length - 1]]; + }; + const diffConsecutive = (array, sequence) => { + for (let i = 0; i <= array.length - sequence.length; i++) { + let j; + for (j = 0; j < sequence.length; j++) { + if (array[i + j] !== sequence[j]) { + break; + } + } + if (j === sequence.length) { + return true; + } + } + return false; + }; + + let routeRemark = useMemo( + () => { + let remark = ""; + if (terminus.serviceType >= 2) { + for (let [, data] of Object.entries(routeList)) { + if (Number(data.serviceType) === 1 && + route === data.route && + JSON.stringify(bound) === JSON.stringify(data.bound) && + (co[0] === "gmb" ? gtfsId === data.gtfsId : JSON.stringify(co) === JSON.stringify(data.co))) + { + if (data.dest.zh !== dest.zh) { + remark = t("開往") + dest[i18n.language]; + } else if (data.orig.zh !== orig.zh) { + if (!terminus.nlbId) { + remark = t("從") + orig[i18n.language] + t("開出"); + } + } else { + let mainRouteFirstStop = stopList[data.stops[co][0]].name; + let mainRouteLastStop = stopList[data.stops[co][data.stops[co].length - 1]].name; + let routeFirstStop = stopList[stops[co][0]].name; + let routeLastStop = stopList[stops[co][stops[co].length - 1]].name; + + if (mainRouteLastStop.zh !== routeLastStop.zh) { + remark = t("開往") + routeLastStop[i18n.language]; + } else if (mainRouteFirstStop.zh !== routeFirstStop.zh) { + if (!terminus.nlbId) { + remark = t("從") + routeFirstStop[i18n.language] + t("開出"); + } + } else { + let difference = stops[co] + .filter(x => !data.stops[co].includes(x)); + let diffName = difference + .map(x => stopList[x].name[i18n.language]); + if (difference.length > 0) { + remark = t("經") + firstLastDiff(diffName).join(t(diffConsecutive(data.stops[co], difference) ? "至" : "及")); + } else { + let difference = data.stops[co] + .filter(x => !stops[co].includes(x)); + let diffName = difference + .map(x => stopList[x].name[i18n.language]); + if (difference.length > 0) { + remark = t("不經") + firstLastDiff(diffName).join(t(diffConsecutive(data.stops[co], difference) ? "至" : "及")); + } + } + } + } + break; + } + } + } + if (terminus.nlbId) { + remark = t("從") + toProperCase(terminus.orig[i18n.language]) + t("開出") + " " + remark; + } + return remark; + }, + [terminus, routeList, i18n.language, bound, co, dest, gtfsId, orig, route, stopList, stops, t] + ); return ( {`${t("往")} `} - + {toProperCase(terminus.dest[i18n.language])} - - {toProperCase(terminus.orig[i18n.language])} + + {routeRemark} diff --git a/src/components/route-eta/RouteHeader.tsx b/src/components/route-eta/RouteHeader.tsx index 2e5746040ef4..bac39e94b4d4 100644 --- a/src/components/route-eta/RouteHeader.tsx +++ b/src/components/route-eta/RouteHeader.tsx @@ -1,7 +1,7 @@ import React, { useContext } from "react"; import { Box, Paper, SxProps, Theme, Typography } from "@mui/material"; import RouteNo from "../route-board/RouteNo"; -import { toProperCase } from "../../utils"; +import { toProperCase, langSpace } from "../../utils"; import { useTranslation } from "react-i18next"; import AppContext from "../../AppContext"; import ReverseButton from "./ReverseButton"; @@ -19,8 +19,8 @@ const RouteHeader = ({ routeId }: { routeId: string }) => { - {t("往")} {toProperCase(dest[i18n.language])}{" "} - {nlbId ? t("由") + " " + toProperCase(orig[i18n.language]) : ""} + {t("往")}{langSpace(i18n)}{toProperCase(dest[i18n.language])}{" "} + {nlbId ? t("從") + toProperCase(orig[i18n.language]) + t("開出") : ""} diff --git a/src/i18n/translation.json b/src/i18n/translation.json index e7aded982dcd..d4c97c72bd42 100644 --- a/src/i18n/translation.json +++ b/src/i18n/translation.json @@ -25,7 +25,14 @@ "設定": "Settings", "取消": "Clear", "路線": "Route", - "你的位置": "Your Location", + "從": "From ", + "開出": "", + "開往": "To ", + "經": "Via ", + "不經": "Skipping ", + "至": " to ", + "及": " and ", + "你的位置": "Your location", "目的地": "Destination", "已複製到剪貼簿": "Copied to clipboard", "資料更新中": "Data updating", diff --git a/src/utils.ts b/src/utils.ts index c8b64933fe4b..a27978d0bcf4 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -2,6 +2,11 @@ import type { Company, EtaDb, Location, RouteList, StopList } from "hk-bus-eta"; import type { Location as GeoLocation } from "hk-bus-eta"; import type { TransportType } from "./typing"; import { isRouteAvaliable } from "./timetable"; + +export const langSpace = (i18n) => { + return i18n.language === "en" ? " " : ""; +} + export const getDistance = (a: GeoLocation, b: GeoLocation) => { const R = 6371e3; // metres const φ1 = (a.lat * Math.PI) / 180; // φ, λ in radians