diff --git a/src/components/side-panel/station-side-panel/more-section.tsx b/src/components/side-panel/station-side-panel/more-section.tsx
index 3cf15d8ea..82aff8d4a 100644
--- a/src/components/side-panel/station-side-panel/more-section.tsx
+++ b/src/components/side-panel/station-side-panel/more-section.tsx
@@ -1,7 +1,7 @@
import { Box, Heading } from '@chakra-ui/react';
import { RmgButtonGroup, RmgFields, RmgFieldsField } from '@railmapgen/rmg-components';
import { useTranslation } from 'react-i18next';
-import { FACILITIES, Facilities, RmgStyle, Services, TEMP } from '../../../constants/constants';
+import { FACILITIES, Facilities, PanelTypeShmetro, RmgStyle, Services, TEMP } from '../../../constants/constants';
import { useRootDispatch, useRootSelector } from '../../../redux';
import {
updateStationCharacterSpacing,
@@ -20,7 +20,7 @@ export default function MoreSection() {
const dispatch = useRootDispatch();
const selectedStation = useRootSelector(state => state.app.selectedStation);
- const { style, loop } = useRootSelector(state => state.param);
+ const { style, loop, info_panel_type } = useRootSelector(state => state.param);
const { services, facility, loop_pivot, one_line, int_padding, character_spacing, underConstruction } =
useRootSelector(state => state.param.stn_list[selectedStation]);
@@ -79,7 +79,7 @@ export default function MoreSection() {
label: t('StationSidePanel.more.oneLine'),
isChecked: one_line,
onChange: checked => dispatch(updateStationOneLine(selectedStation, checked)),
- hidden: ![RmgStyle.SHMetro].includes(style),
+ hidden: !(style === RmgStyle.SHMetro && info_panel_type !== PanelTypeShmetro.sh2024),
minW: 'full',
oneLine: true,
},
diff --git a/src/constants/constants.ts b/src/constants/constants.ts
index e038d7027..6ae4273ff 100644
--- a/src/constants/constants.ts
+++ b/src/constants/constants.ts
@@ -192,6 +192,7 @@ export enum PanelTypeGZMTR {
export enum PanelTypeShmetro {
sh = 'sh',
sh2020 = 'sh2020',
+ sh2024 = 'sh2024',
}
/**
diff --git a/src/i18n/translations/en.json b/src/i18n/translations/en.json
index 9a71177a7..60ea30da3 100644
--- a/src/i18n/translations/en.json
+++ b/src/i18n/translations/en.json
@@ -86,7 +86,8 @@
"gz1421": "2017 style",
"gz7w": "2022 style",
"sh": "Default",
- "sh2020": "2020 (Beta)",
+ "sh2020": "2020",
+ "sh2024": "2024 (Beta)",
"nameDisplay": "Display station names",
"alternatively": "Alternatively",
"onOneSide": "Same side",
diff --git a/src/i18n/translations/ja.json b/src/i18n/translations/ja.json
index 663e1c9bc..12e3d894a 100644
--- a/src/i18n/translations/ja.json
+++ b/src/i18n/translations/ja.json
@@ -84,7 +84,8 @@
"gz1421": "2017風格",
"gz7w": "2022風格",
"sh": "デフォルト",
- "sh2020": "2020風格(プレビュー版)",
+ "sh2020": "2020風格",
+ "sh2024": "2024風格(プレビュー版)",
"nameDisplay": "駅名表示",
"alternatively": "交互表示",
"onOneSide": "片側表示",
diff --git a/src/i18n/translations/ko.json b/src/i18n/translations/ko.json
index 6c9ec4086..6dc6181a5 100644
--- a/src/i18n/translations/ko.json
+++ b/src/i18n/translations/ko.json
@@ -84,6 +84,7 @@
"gz7w": "2022년 모양",
"sh": "묵인",
"sh2020": "2020모양(사전 검토)",
+ "sh2024": "2024모양",
"nameDisplay": "역 명칭 보이기",
"alternatively": "교차 표시",
"onOneSide": "같은 쪽",
diff --git a/src/i18n/translations/zh-Hans.json b/src/i18n/translations/zh-Hans.json
index 171e863d5..37d573ecb 100644
--- a/src/i18n/translations/zh-Hans.json
+++ b/src/i18n/translations/zh-Hans.json
@@ -84,7 +84,8 @@
"gz1421": "2017样式",
"gz7w": "2022样式",
"sh": "默认",
- "sh2020": "2020样式(预览版)",
+ "sh2020": "2020样式",
+ "sh2024": "2024样式(预览版)",
"nameDisplay": "显示车站名称",
"alternatively": "交错显示",
"onOneSide": "同一侧",
diff --git a/src/i18n/translations/zh-Hant.json b/src/i18n/translations/zh-Hant.json
index 6bd308d59..d42fbf7b3 100644
--- a/src/i18n/translations/zh-Hant.json
+++ b/src/i18n/translations/zh-Hant.json
@@ -79,7 +79,8 @@
"gz1421": "2017樣式",
"gz7w": "2022樣式",
"sh": "預設",
- "sh2020": "2020樣式(預覽版)",
+ "sh2020": "2020樣式",
+ "sh2024": "2024樣式(預覽版)",
"nameDisplay": "顯示車站名稱",
"alternatively": "交錯顯示",
"onOneSide": "同一側",
diff --git a/src/svgs/shmetro/indoor/indoor-shmetro.tsx b/src/svgs/shmetro/indoor/indoor-shmetro.tsx
index f9c453120..8a8f88fbc 100644
--- a/src/svgs/shmetro/indoor/indoor-shmetro.tsx
+++ b/src/svgs/shmetro/indoor/indoor-shmetro.tsx
@@ -2,7 +2,7 @@ import { memo, useMemo } from 'react';
import { adjacencyList, criticalPathMethod, getStnState, getXShareMTR } from '../../methods/share';
import StationSHMetro from './station-shmetro';
import { StationsSHMetro } from '../../methods/mtr';
-import { CanvasType, Services, StationDict } from '../../../constants/constants';
+import { CanvasType, PanelTypeShmetro, Services, StationDict } from '../../../constants/constants';
import { useRootSelector } from '../../../redux';
import LoopSHMetro from '../loop/loop-shmetro';
import SvgWrapper from '../../svg-wrapper';
@@ -11,7 +11,13 @@ const CANVAS_TYPE = CanvasType.Indoor;
export default function IndoorWrapperSHMetro() {
const { canvasScale } = useRootSelector(state => state.app);
- const { svgWidth: svgWidths, svg_height: svgHeight, theme, loop } = useRootSelector(store => store.param);
+ const {
+ svgWidth: svgWidths,
+ svg_height: svgHeight,
+ theme,
+ loop,
+ info_panel_type,
+ } = useRootSelector(store => store.param);
const svgWidth = svgWidths[CANVAS_TYPE];
@@ -25,12 +31,12 @@ export default function IndoorWrapperSHMetro() {
>
{loop ? : }
-
+ {info_panel_type !== PanelTypeShmetro.sh2024 ? : }
);
}
-export const DefsSHMetro = memo(function DefsSHMetro() {
+const DefsSHMetro = memo(function DefsSHMetro() {
return (
@@ -61,6 +67,32 @@ export const DefsSHMetro = memo(function DefsSHMetro() {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
});
@@ -89,7 +121,7 @@ const IndoorSHMetro = () => {
const realCP = criticalPathMethod(criticalPath.nodes[1], criticalPath.nodes.slice(-2)[0], adjMat);
const xShares = useMemo(() => {
- console.log('computing x shares');
+ console.debug('computing x shares');
return Object.keys(param.stn_list).reduce(
(acc, cur) => ({ ...acc, [cur]: getXShareMTR(cur, adjMat, branches) }),
{} as { [stnId: string]: number }
@@ -142,10 +174,16 @@ const IndoorSHMetro = () => {
0
);
+ const lineBadgeDX = Math.min(
+ ...Object.entries(xs)
+ .filter(([k]) => !['linestart', 'lineend'].includes(k))
+ .map(([, v]) => v)
+ );
return (
+ {param.info_panel_type === PanelTypeShmetro.sh2024 && }
);
};
@@ -286,6 +324,51 @@ const InfoElements = memo(() => {
InfoElements.displayName = 'InfoElements';
+const InfoElements2024 = () => {
+ const {
+ svg_height,
+ svgWidth: { indoor: svg_width },
+ } = useRootSelector(store => store.param);
+
+ return (
+
+
+ 友情提示:请留意您需要换乘线路的首末班时间,以免耽误您的出行,末班车进站前三分钟停售该末班车车票。
+
+
+ Please pay attention to the interchange schedule if you want to transfer to other lines. Stop selling
+ tickets 3 minutes before the last train services.
+
+
+ );
+};
+
+const LineBadge = (props: { dx: number }) => {
+ const { dx } = props;
+ const { line_name, theme } = useRootSelector(store => store.param);
+ const num = line_name[0].match(/^(\d+)号线$/)?.[1] ?? '';
+ const width = num.length > 1 ? 26.4 : 21.6;
+ const textDX = num.length > 1 ? 0 : 4;
+ const letterSpacing = num.length > 1 ? -1.5 : 0;
+ const padding = 15;
+ return (
+
+
+
+ {num}
+
+
+ );
+};
+
/* Some unused functions to split branches from the main line.
* Note the branches here has a slightly different meaning.
* It refers to all the line sections that have a parallel line
diff --git a/src/svgs/shmetro/indoor/station-shmetro.tsx b/src/svgs/shmetro/indoor/station-shmetro.tsx
index 0d1f9eb6b..5b6bca2dc 100644
--- a/src/svgs/shmetro/indoor/station-shmetro.tsx
+++ b/src/svgs/shmetro/indoor/station-shmetro.tsx
@@ -1,8 +1,14 @@
import { ColourHex } from '@railmapgen/rmg-palette-resources';
+import { Translation } from '@railmapgen/rmg-translate';
import { Fragment, Ref, SVGProps, forwardRef, useEffect, useMemo, useRef, useState } from 'react';
-import { ExtendedInterchangeInfo, InterchangeGroup, Services } from '../../../constants/constants';
+import {
+ ExtendedInterchangeInfo,
+ InterchangeGroup,
+ PanelTypeGZMTR,
+ PanelTypeShmetro,
+ Services,
+} from '../../../constants/constants';
import { useRootSelector } from '../../../redux';
-import { Translation } from '@railmapgen/rmg-translate';
/**
* Which direction to display station name. Currently shmetro only.
@@ -18,15 +24,53 @@ interface Props {
export const StationSHMetro = (props: Props) => {
const { stnId, nameDirection, services, color } = props;
- const stnInfo = useRootSelector(store => store.param.stn_list[stnId]);
+ const { stn_list, info_panel_type } = useRootSelector(store => store.param);
+ const stnInfo = stn_list[stnId];
- const transfer = [...(stnInfo.transfer.groups[0]?.lines || []), ...(stnInfo.transfer.groups[1]?.lines || [])];
let stationIconStyle: string;
- if (stnInfo.services.length === 3) stationIconStyle = 'direct_indoor_sh';
- else if (stnInfo.services.length === 2) stationIconStyle = 'express_indoor_sh';
- else if (stnInfo.transfer.groups[1]?.lines?.length ?? 0 > 0) stationIconStyle = 'osi_indoor_sh';
- else if (transfer.length > 0) stationIconStyle = 'int2_indoor_sh';
- else stationIconStyle = 'stn_indoor_sh';
+ const stationIconColor: { [pos: string]: string } = {};
+ if (info_panel_type === PanelTypeShmetro.sh2024) {
+ const int_length = stnInfo.transfer.groups.at(0)?.lines?.length ?? 0;
+ const osi_osysi_length = [
+ ...(stnInfo.transfer.groups.at(1)?.lines || []),
+ ...(stnInfo.transfer.groups.at(2)?.lines || []),
+ ].length;
+
+ stationIconColor.stroke = 'var(--rmg-theme-colour)';
+ if (stnInfo.services.length === 3) {
+ stationIconStyle = 'stn_sh_2020_direct';
+ } else if (stnInfo.services.length === 2) {
+ stationIconStyle = 'stn_sh_2020_express';
+ } else if (osi_osysi_length > 1) {
+ // 不管多少条站内换乘,只要有超过1个的出站换乘就是3个圆了
+ stationIconStyle = 'stn_sh_2024_osysi3';
+ } else if (int_length > 0 && osi_osysi_length === 0) {
+ // 仅换乘车站
+ stationIconStyle = 'stn_sh_2024_int';
+ } else if (int_length > 0 && osi_osysi_length > 0) {
+ // 站内换乘+出站换乘
+ stationIconStyle = 'stn_sh_2024_int_osysi';
+ } else if (int_length === 0 && osi_osysi_length === 1) {
+ // 仅2线出站换乘
+ stationIconStyle = 'stn_sh_2024_osysi2';
+ } else {
+ stationIconStyle = 'stn_sh_2024';
+ delete stationIconColor.stroke;
+ stationIconColor.fill = 'var(--rmg-theme-colour)';
+ }
+ } else {
+ const non_osysi_transfer = [
+ ...(stnInfo.transfer.groups[0]?.lines || []),
+ ...(stnInfo.transfer.groups[1]?.lines || []),
+ ];
+ if (stnInfo.services.length === 3) stationIconStyle = 'direct_indoor_sh';
+ else if (stnInfo.services.length === 2) stationIconStyle = 'express_indoor_sh';
+ else if (stnInfo.transfer.groups[1]?.lines?.length ?? 0 > 0) stationIconStyle = 'osi_indoor_sh';
+ else if (non_osysi_transfer.length > 0) stationIconStyle = 'int2_indoor_sh';
+ else stationIconStyle = 'stn_indoor_sh';
+ stationIconColor.stroke =
+ non_osysi_transfer.length > 0 ? 'var(--rmg-black)' : (color ?? 'var(--rmg-theme-colour)');
+ }
const dr = nameDirection === 'left' || nameDirection === 'right' ? 90 : 0;
return (
@@ -39,8 +83,8 @@ export const StationSHMetro = (props: Props) => {
/>