From 9ab519b8f6feca5a098f05932931b2775a1ae73d Mon Sep 17 00:00:00 2001 From: tahodev <85001874+tahodev@users.noreply.github.com> Date: Wed, 14 Oct 2026 22:57:06 +0900 Subject: [PATCH 1/3] =?UTF-8?q?docs:=20404=E3=81=AB=E3=81=AA=E3=81=A3?= =?UTF-8?q?=E3=81=A6=E3=81=84=E3=81=9F=E5=A4=96=E9=83=A8=E3=83=AA=E3=83=B3?= =?UTF-8?q?=E3=82=AF2=E4=BB=B6=E3=82=92=E4=BF=AE=E6=AD=A3=20(#1720)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: 404になっていた外部リンク2件を修正 - README.md: all-contributors の emoji key リンクを現行URL(https://allcontributors.org/emoji-key)に更新 - docs/gtfs-bus-integration-research.md: 国土交通省「静的バス情報フォーマット(GTFS-JP)仕様書」の旧HTMLページが404のため、同一ドキュメントの現行PDF(001981081.pdf)に差し替え * docs: GTFS-JP仕様書リンクを現行のv4に更新 CodeRabbitの指摘対応。差し替えたPDF(001981081.pdf)は第3版(2021年7月)の アーカイブ版だったため、参考資料として現行仕様である「公共交通運行情報標準 データ仕様(GTFS-JP) v4」へのリンクに名称ごと更新。 --------- Co-authored-by: Instinct Agent Co-authored-by: Tsubasa SEKIGUCHI --- README.md | 2 +- docs/gtfs-bus-integration-research.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 315791e4..d68c86ae 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ This project includes a comprehensive dataset of Japanese railway information in ## Contributors ✨ -Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): +Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/emoji-key)): diff --git a/docs/gtfs-bus-integration-research.md b/docs/gtfs-bus-integration-research.md index 18b5699d..c01f19af 100644 --- a/docs/gtfs-bus-integration-research.md +++ b/docs/gtfs-bus-integration-research.md @@ -563,4 +563,4 @@ distance -- 駅間距離(メートル) ### 国土交通省 -- [静的バス情報フォーマット(GTFS-JP)仕様書](https://www.mlit.go.jp/sogoseisaku/transport/sosei_transport_tk_000112.html) +- [公共交通運行情報標準データ仕様(GTFS-JP)v4](https://www.mlit.go.jp/commmmons/document/007/commmmons_doc_007-02_ver01.pdf) From 6931d523de95389a1d611171f14e3a54379081f6 Mon Sep 17 00:00:00 2001 From: Tsubasa SEKIGUCHI Date: Fri, 16 Oct 2026 09:33:07 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=E4=BA=AC=E7=8E=8B=E7=B7=9A=E7=B3=BB?= =?UTF-8?q?=E7=B5=B1=E3=81=AE=E5=81=9C=E8=BB=8A=E9=A7=85=E3=82=92=E7=85=A7?= =?UTF-8?q?=E5=90=88=E3=81=97=E6=80=A5=E8=A1=8C=E3=83=BB=E4=BA=AC=E7=8E=8B?= =?UTF-8?q?=E3=83=A9=E3=82=A4=E3=83=8A=E3=83=BC=E3=81=AE=E5=81=9C=E8=BB=8A?= =?UTF-8?q?=E6=BC=8F=E3=82=8C=E3=82=92=E4=BF=AE=E6=AD=A3=20(#1723)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 + data/5!station_station_types.csv | 12 +- data_validator/tests/fixtures/keio_stops.csv | 54 +++++++++ .../tests/keio_stopping_patterns.rs | 111 ++++++++++++++++++ docs/keio-stopping-pattern-audit.md | 30 +++++ 5 files changed, 203 insertions(+), 6 deletions(-) create mode 100644 data_validator/tests/fixtures/keio_stops.csv create mode 100644 data_validator/tests/keio_stopping_patterns.rs create mode 100644 docs/keio-stopping-pattern-audit.md diff --git a/README.md b/README.md index d68c86ae..1b4ab33c 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ A GraphQL API that provides nearby Japanese train stations and bus stops, runnin - For system architecture and design decisions, see [docs/architecture.md](docs/architecture.md). - For the design of the transfer route search (`connectedRoutes`, RAPTOR), see [docs/route-search.md](docs/route-search.md). - For the source-backed operating constraints used by timetable-free search, see [docs/route-service-audit.md](docs/route-service-audit.md). +- For the Keio stopping-pattern audit and regression checks, see [docs/keio-stopping-pattern-audit.md](docs/keio-stopping-pattern-audit.md). - For technical debt analysis and architectural concerns, see [docs/technical_debt.md](docs/technical_debt.md). - For the record of the Cloudflare Workers migration, see [docs/cloudflare-workers-migration.md](docs/cloudflare-workers-migration.md). - For the published GraphQL schema, see [schema/public.graphql](schema/public.graphql). @@ -109,3 +110,4 @@ make deploy-production # production -> stationapi The data lives inside the WASM binary, so **a data change needs a rebuild and a redeploy**; it is not picked up at runtime. + diff --git a/data/5!station_station_types.csv b/data/5!station_station_types.csv index c2827588..81344aa9 100644 --- a/data/5!station_station_types.csv +++ b/data/5!station_station_types.csv @@ -2022,7 +2022,7 @@ DEFAULT,9950213,203,64,0,修善寺 DEFAULT,2400101,400,65,0,新宿 DEFAULT,2400104,400,65,1,笹塚 DEFAULT,2400105,400,65,1,代田橋 -DEFAULT,2400106,400,65,1,明大前 +DEFAULT,2400106,400,65,0,明大前 DEFAULT,2400107,400,65,1,下高井戸 DEFAULT,2400108,400,65,1,桜上水 DEFAULT,2400109,400,65,1,上北沢 @@ -2049,12 +2049,12 @@ DEFAULT,2400129,400,65,0,高幡不動 DEFAULT,2400130,400,65,1,南平 DEFAULT,2400131,400,65,1,平山城址公園 DEFAULT,2400132,400,65,1,長沼 -DEFAULT,2400133,400,65,1,北野 +DEFAULT,2400133,400,65,0,北野 DEFAULT,2400134,400,65,0,京王八王子 DEFAULT,2400101,401,66,0,新宿 DEFAULT,2400104,401,66,1,笹塚 DEFAULT,2400105,401,66,1,代田橋 -DEFAULT,2400106,401,66,1,明大前 +DEFAULT,2400106,401,66,0,明大前 DEFAULT,2400107,401,66,1,下高井戸 DEFAULT,2400108,401,66,1,桜上水 DEFAULT,2400109,401,66,1,上北沢 @@ -11375,7 +11375,7 @@ DEFAULT,2400110,382,285,1,八幡山 DEFAULT,2400111,382,285,1,芦花公園 DEFAULT,2400112,382,285,0,千歳烏山 DEFAULT,2400113,382,285,1,仙川 -DEFAULT,2400114,382,285,1,つつじヶ丘 +DEFAULT,2400114,382,285,0,つつじヶ丘 DEFAULT,2400115,382,285,1,柴崎 DEFAULT,2400116,382,285,1,国領 DEFAULT,2400117,382,285,1,布田 @@ -28232,7 +28232,7 @@ DEFAULT,2400110,382,757,1,八幡山 DEFAULT,2400111,382,757,1,芦花公園 DEFAULT,2400112,382,757,0,千歳烏山 DEFAULT,2400113,382,757,1,仙川 -DEFAULT,2400114,382,757,1,つつじヶ丘 +DEFAULT,2400114,382,757,0,つつじヶ丘 DEFAULT,2400115,382,757,1,柴崎 DEFAULT,2400116,382,757,1,国領 DEFAULT,2400117,382,757,1,布田 @@ -28336,7 +28336,7 @@ DEFAULT,2400110,382,760,1,八幡山 DEFAULT,2400111,382,760,1,芦花公園 DEFAULT,2400112,382,760,0,千歳烏山 DEFAULT,2400113,382,760,1,仙川 -DEFAULT,2400114,382,760,1,つつじヶ丘 +DEFAULT,2400114,382,760,0,つつじヶ丘 DEFAULT,2400115,382,760,1,柴崎 DEFAULT,2400116,382,760,1,国領 DEFAULT,2400117,382,760,1,布田 diff --git a/data_validator/tests/fixtures/keio_stops.csv b/data_validator/tests/fixtures/keio_stops.csv new file mode 100644 index 00000000..34d4f6bb --- /dev/null +++ b/data_validator/tests/fixtures/keio_stops.csv @@ -0,0 +1,54 @@ +station_number,stopping_types,source,checked_on +1,各駅停車|快速|区間急行|急行|特急|京王ライナー|Mt.TAKAO号,https://www.keio.co.jp/train/station/ko01_shinjuku/,2026-10-16 +2,各駅停車|快速|区間急行|急行,https://www.keio.co.jp/train/station/ko02_hatsudai/,2026-10-16 +3,各駅停車|快速|区間急行|急行,https://www.keio.co.jp/train/station/ko03_hatagaya/,2026-10-16 +4,各駅停車|快速|区間急行|急行|特急,https://www.keio.co.jp/train/station/ko04_sasazuka/,2026-10-16 +5,各駅停車,https://www.keio.co.jp/train/station/ko05_daitabashi/,2026-10-16 +6,各駅停車|快速|区間急行|急行|特急|京王ライナー|Mt.TAKAO号,https://www.keio.co.jp/train/station/ko06in08_meidaimae/,2026-10-16 +7,各駅停車|快速,https://www.keio.co.jp/train/station/ko07_shimo-takaido/,2026-10-16 +8,各駅停車|快速|区間急行|急行,https://www.keio.co.jp/train/station/ko08_sakurajosui/,2026-10-16 +9,各駅停車,https://www.keio.co.jp/train/station/ko09_kami-kitazawa/,2026-10-16 +10,各駅停車|快速,https://www.keio.co.jp/train/station/ko10_hachiman-yama/,2026-10-16 +11,各駅停車,https://www.keio.co.jp/train/station/ko11_roka-koen/,2026-10-16 +12,各駅停車|快速|区間急行|急行|特急,https://www.keio.co.jp/train/station/ko12_chitose-karasuyama/,2026-10-16 +13,各駅停車|快速|区間急行,https://www.keio.co.jp/train/station/ko13_sengawa/,2026-10-16 +14,各駅停車|快速|区間急行|急行,https://www.keio.co.jp/train/station/ko14_tsutsujigaoka/,2026-10-16 +15,各駅停車,https://www.keio.co.jp/train/station/ko15_shibasaki/,2026-10-16 +16,各駅停車,https://www.keio.co.jp/train/station/ko16_kokuryo/,2026-10-16 +17,各駅停車,https://www.keio.co.jp/train/station/ko17_fuda/,2026-10-16 +18,各駅停車|快速|区間急行|急行|特急,https://www.keio.co.jp/train/station/ko18_chofu/,2026-10-16 +19,各駅停車|快速,https://www.keio.co.jp/train/station/ko19_nishi-chofu/,2026-10-16 +20,各駅停車|快速,https://www.keio.co.jp/train/station/ko20_tobitakyu/,2026-10-16 +21,各駅停車|快速,https://www.keio.co.jp/train/station/ko21_musashinodai/,2026-10-16 +22,各駅停車|快速,https://www.keio.co.jp/train/station/ko22_tama-reien/,2026-10-16 +23,各駅停車|快速|区間急行|急行,https://www.keio.co.jp/train/station/ko23_higashi-fuchu/,2026-10-16 +24,各駅停車|快速|区間急行|急行|特急|京王ライナー|Mt.TAKAO号,https://www.keio.co.jp/train/station/ko24_fuchu/,2026-10-16 +25,各駅停車|快速|区間急行|急行|特急|京王ライナー|Mt.TAKAO号,https://www.keio.co.jp/train/station/ko25_bubaigawara/,2026-10-16 +26,各駅停車|快速|区間急行,https://www.keio.co.jp/train/station/ko26_nakagawara/,2026-10-16 +27,各駅停車|快速|区間急行|急行|特急|京王ライナー|Mt.TAKAO号,https://www.keio.co.jp/train/station/ko27_seiseki-sakuragaoka/,2026-10-16 +28,各駅停車|快速|区間急行,https://www.keio.co.jp/train/station/ko28_mogusaen/,2026-10-16 +29,各駅停車|快速|区間急行|急行|特急|京王ライナー|Mt.TAKAO号,https://www.keio.co.jp/train/station/ko29_takahatafudo/,2026-10-16 +30,各駅停車|快速|区間急行,https://www.keio.co.jp/train/station/ko30_minamidaira/,2026-10-16 +31,各駅停車|快速|区間急行,https://www.keio.co.jp/train/station/ko31_hirayamajoshi-koen/,2026-10-16 +32,各駅停車|快速|区間急行,https://www.keio.co.jp/train/station/ko32_naganuma/,2026-10-16 +33,各駅停車|快速|区間急行|急行|特急|京王ライナー|Mt.TAKAO号,https://www.keio.co.jp/train/station/ko33_kitano/,2026-10-16 +34,各駅停車|快速|区間急行|急行|特急|京王ライナー,https://www.keio.co.jp/train/station/ko34_keio-hachioji/,2026-10-16 +35,各駅停車|快速|区間急行,https://www.keio.co.jp/train/station/ko35_keio-tamagawa/,2026-10-16 +36,各駅停車|快速|区間急行|急行|特急,https://www.keio.co.jp/train/station/ko36_keio-inadazutsumi/,2026-10-16 +37,各駅停車|快速|区間急行,https://www.keio.co.jp/train/station/ko37_keio-yomiuri-land/,2026-10-16 +38,各駅停車|快速|区間急行,https://www.keio.co.jp/train/station/ko38_inagi/,2026-10-16 +39,各駅停車|快速|区間急行,https://www.keio.co.jp/train/station/ko39_wakabadai/,2026-10-16 +40,各駅停車|快速|区間急行|急行|特急|京王ライナー,https://www.keio.co.jp/train/station/ko40_keio-nagayama/,2026-10-16 +41,各駅停車|快速|区間急行|急行|特急|京王ライナー,https://www.keio.co.jp/train/station/ko41_keio-tama-center/,2026-10-16 +42,各駅停車|快速|区間急行,https://www.keio.co.jp/train/station/ko42_keio-horinouchi/,2026-10-16 +43,各駅停車|快速|区間急行|急行|特急|京王ライナー,https://www.keio.co.jp/train/station/ko43_minami-osawa/,2026-10-16 +44,各駅停車|快速|区間急行,https://www.keio.co.jp/train/station/ko44_tamasakai/,2026-10-16 +45,各駅停車|快速|区間急行|急行|特急|京王ライナー,https://www.keio.co.jp/train/station/ko45_hashimoto/,2026-10-16 +46,各駅停車|急行|特急,https://www.keio.co.jp/train/station/ko46_fuchukeiba-seimommae/,2026-10-16 +47,各駅停車|急行,https://www.keio.co.jp/train/station/ko47_tama-dobutsukoen/,2026-10-16 +48,各駅停車|快速|区間急行|特急,https://www.keio.co.jp/train/station/ko48_keio-katakura/,2026-10-16 +49,各駅停車|快速|区間急行|特急,https://www.keio.co.jp/train/station/ko49_yamada/,2026-10-16 +50,各駅停車|快速|区間急行|急行|特急|京王ライナー|Mt.TAKAO号,https://www.keio.co.jp/train/station/ko50_mejirodai/,2026-10-16 +51,各駅停車|快速|区間急行|特急,https://www.keio.co.jp/train/station/ko51_hazama/,2026-10-16 +52,各駅停車|快速|区間急行|急行|特急|京王ライナー|Mt.TAKAO号,https://www.keio.co.jp/train/station/ko52_takao/,2026-10-16 +53,各駅停車|快速|区間急行|急行|特急|京王ライナー|Mt.TAKAO号,https://www.keio.co.jp/train/station/ko53_takaosanguchi/,2026-10-16 diff --git a/data_validator/tests/keio_stopping_patterns.rs b/data_validator/tests/keio_stopping_patterns.rs new file mode 100644 index 00000000..a4e052cb --- /dev/null +++ b/data_validator/tests/keio_stopping_patterns.rs @@ -0,0 +1,111 @@ +use std::collections::{BTreeMap, BTreeSet, HashMap}; +use std::path::Path; + +use csv::StringRecord; + +fn records(path: &Path) -> Vec { + csv::Reader::from_path(path) + .unwrap() + .records() + .collect::>() + .unwrap() +} + +// Line-specific station IDs at junctions must appear on both sides, in order. +fn sections(group: u32) -> Vec<(u32, u32, u32)> { + match group { + 65 | 67..=71 => vec![(24001, 1, 34)], + 66 | 252 | 416 | 760..=762 => vec![(24001, 1, 18), (24002, 18, 45)], + 253 | 412..=415 | 758 | 759 => vec![(24001, 1, 33), (24003, 33, 53)], + 254 | 285..=287 | 757 => { + vec![(24007, 1, 4), (24001, 4, 18), (24002, 18, 45)] + } + 255 => vec![(24007, 1, 4), (24001, 4, 33), (24003, 33, 53)], + 756 => vec![(24007, 1, 4), (24001, 4, 34)], + 763 | 764 => vec![(24001, 1, 23), (24004, 23, 46)], + 765 => vec![(24004, 23, 46)], + 766 => vec![(24001, 1, 29), (24005, 29, 47)], + 767 => vec![(24005, 29, 47)], + _ => panic!("unaudited Keio group: {group}"), + } +} + +#[test] +fn existing_keio_patterns_match_official_stops_and_complete_station_sequences() { + let root = Path::new(env!("CARGO_MANIFEST_DIR")).join(".."); + let data = root.join("data"); + let stations = records(&data.join("3!stations.csv")); + let station_by_id: HashMap<&str, &StringRecord> = stations.iter().map(|r| (&r[0], r)).collect(); + let types = records(&data.join("4!types.csv")); + let type_names: HashMap<&str, &str> = types.iter().map(|r| (&r[1], &r[2])).collect(); + let fixture = records(&root.join("data_validator/tests/fixtures/keio_stops.csv")); + let official: HashMap = fixture + .iter() + .map(|r| (r[0].parse().unwrap(), &r[1])) + .collect(); + assert_eq!(official.len(), 53); + + let mut actual: BTreeMap> = BTreeMap::new(); + for row in records(&data.join("5!station_station_types.csv")) { + let station = station_by_id[&row[1]]; + let line: u32 = station[13].parse().unwrap(); + if !matches!(line, 24001..=24005 | 24007) { + continue; + } + let number: u32 = station[8].parse().unwrap(); + let group: u32 = row[3].parse().unwrap(); + let name = type_names[&row[2]]; + let category = if name.starts_with("京王ライナー") { + "京王ライナー" + } else if name == "Mt.TAKAO" { + "Mt.TAKAO号" + } else { + name + }; + // Per-row type is essential: Toei locals become Keio express services. + let mut expected = u32::from(!official[&number].split('|').any(|t| t == category)); + if group == 758 { + // Mt.TAKAO down: Shinjuku, Meidaimae, Takaosanguchi only. + expected = u32::from(!matches!(number, 1 | 6 | 53)); + } + if number == 23 && category == "特急" { + // Racecourse through service stops; main-line services partly stop. + expected = if group == 764 { 0 } else { 5 }; + } + assert_eq!( + row[4].parse::().unwrap(), + expected, + "group {group}, station {} ({}), type {name}", + &station[2], + &station[0] + ); + actual.entry(group).or_default().push(row[1].to_owned()); + } + + let audited: BTreeSet = [ + 65, 66, 67, 68, 69, 70, 71, 252, 253, 254, 255, 285, 286, 287, 412, 413, 414, 415, 416, + 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, + ] + .into_iter() + .collect(); + assert_eq!(actual.keys().copied().collect::>(), audited); + for (group, station_ids) in actual { + let mut expected = Vec::new(); + for (line, first, last) in sections(group) { + let mut section: Vec<&StringRecord> = stations + .iter() + .filter(|r| { + r[13].parse::().unwrap() == line + && &r[21] == "0" + && (first..=last).contains(&r[8].parse::().unwrap()) + }) + .collect(); + section.sort_by_key(|r| (r[22].parse::().unwrap(), r[0].to_owned())); + expected.extend(section.into_iter().map(|r| r[0].to_owned())); + } + assert_eq!( + station_ids, expected, + "incomplete/out-of-order group {group}" + ); + } +} diff --git a/docs/keio-stopping-pattern-audit.md b/docs/keio-stopping-pattern-audit.md new file mode 100644 index 00000000..c72aedc5 --- /dev/null +++ b/docs/keio-stopping-pattern-audit.md @@ -0,0 +1,30 @@ +# 京王線系統の停車駅照合(2026-10-16) + +京王線・京王新線・相模原線・高尾線・競馬場線・動物園線の公式各駅案内53駅と、既存31路線グループの936行を照合した。都営新宿線直通の京王区間も含む。駅ごとの参照URLと確認日は `data_validator/tests/fixtures/keio_stops.csv` に収録した。 + +## 修正 + +| 路線グループ | 種別 | 駅 | 修正 | +| --- | --- | --- | --- | +| 285 | 急行(都営線内も急行) | つつじヶ丘 | 通過 → 停車 | +| 757 | 急行(都営線内は各駅停車) | つつじヶ丘 | 通過 → 停車 | +| 760 | 急行(京王線新宿~橋本) | つつじヶ丘 | 通過 → 停車 | +| 65 | 京王ライナー(京王八王子系統) | 明大前・北野 | 通過 → 停車 | +| 66 | 京王ライナー(橋本系統) | 明大前 | 通過 → 停車 | + +急行のつつじヶ丘は[公式駅案内](https://www.keio.co.jp/train/station/ko14_tsutsujigaoka/)、京王ライナーは[上り](https://www.keio.co.jp/zasekishitei/)・[下り](https://www.keio.co.jp/zasekishitei/index_n.html)の公式停車駅・時刻表で確認した。京王ライナーの系統名に「方面」とあるが、既存の方向設定は0(両方向)であり、上りも同じグループを使用する。 + +## 回帰検査 + +`cargo test -p data_validator --test keio_stopping_patterns` で、各行の種別と公式駅案内の停車種別を比較する。都営線内の各駅停車をグループ全体の種別として扱わず、京王区間の各行の `type_cd` を使用する。 + +既存31グループがすべて存在すること、および各グループの路線区間から求めた駅ID列がCSVの列と完全一致することも検証する。これにより行の削除、重複、並び違い、調布・北野・東府中・高幡不動・笹塚の接続部での片側ID欠落を検出する。井の頭線は別線区のためこの検査の対象外。 + +次の差異は公式の運行形態に基づくもので、均一化しない。 + +- [Mt.TAKAO号](https://www.keio.co.jp/zasekishitei/index_mt.html)の758は下り(新宿・明大前・高尾山口)、759は上り(府中以西の所定駅・明大前・新宿)。駅案内の停車種別一覧だけでは方向別の停車駅を表現できないため、グループ別の期待値を使用する。 +- 京王八王子・高尾山口系統の特急は東府中を一部停車(`pass=5`)とし、競馬場線直通特急764は東府中の両路線IDで停車する。 +- 相模原線の急行・特急、高尾線の急行・特急は各線の公式駅案内に従う。特急が高尾線内で各駅に停車しても急行の通過駅まで変更しない。 + +本検査は既存の停車パターンと駅列を対象とする。新系統の収録網羅性、時刻指定検索、乗降制限の実装を保証するものではない。公式案内には高尾線の京王ライナーも掲載されているが、現行CSVには専用の路線グループがなく、系統追加は別途対応が必要。 + From 72b0e3ad4c57849f2d30b7dd9108db1f5c32be81 Mon Sep 17 00:00:00 2001 From: Tsubasa SEKIGUCHI Date: Fri, 16 Oct 2026 09:44:36 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=E9=AB=98=E5=B0=BE=E7=B7=9A=E3=81=AE?= =?UTF-8?q?=E4=BA=AC=E7=8E=8B=E3=83=A9=E3=82=A4=E3=83=8A=E3=83=BC=E3=82=92?= =?UTF-8?q?=E6=96=B0=E5=AE=BF=EF=BD=9E=E9=AB=98=E5=B0=BE=E5=B1=B1=E5=8F=A3?= =?UTF-8?q?=E3=81=AE=E7=8B=AC=E7=AB=8B=E7=B3=BB=E7=B5=B1=E3=81=A8=E3=81=97?= =?UTF-8?q?=E3=81=A6=E8=BF=BD=E5=8A=A0=20(#1724)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/4!types.csv | 1 + data/5!station_station_types.csv | 38 +++++++++++++ data/route_service_rules.csv | 1 + .../tests/keio_stopping_patterns.rs | 4 +- data_validator/tests/keio_takao_liner.rs | 57 +++++++++++++++++++ docs/keio-stopping-pattern-audit.md | 2 +- docs/route-service-audit.md | 12 +++- 7 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 data_validator/tests/keio_takao_liner.rs diff --git a/data/4!types.csv b/data/4!types.csv index d6f60ff6..ef3cf3e4 100644 --- a/data/4!types.csv +++ b/data/4!types.csv @@ -261,6 +261,7 @@ DEFAULT,385,準急,ジュンキュウ,Semi Express,准急,준급,#0000FF,0,3,0, DEFAULT,386,洛楽,ラクラク,Rakuraku,洛乐,라쿠라쿠,#DC143C,0,4,0,京阪用 快速特急,COMPLETE DEFAULT,400,京王ライナー(京王八王子方面),ケイオウライナー,Keio Liner(for Keiō-hachiōji),京王Liner,게이오 라이너,#DD0077,0,2,0,,COMPLETE DEFAULT,401,京王ライナー(橋本方面),ケイオウライナー,Keio Liner(for Hashimoto),京王Liner,게이오 라이너,#DD0078,0,2,0,,COMPLETE +DEFAULT,413,京王ライナー(高尾山口方面),ケイオウライナー,Keio Liner(for Takaosanguchi),京王Liner,게이오 라이너,#DD0077,0,2,0,,COMPLETE DEFAULT,402,モーニングウィング号,モーニングウィングゴウ,"Morning Wing(Miurakaigan to Shinagawa, Sengakuji)",Morning Wing,모닝윙호,#379412,1,2,0,,COMPLETE DEFAULT,403,イブニングウィング号,イブニングウィングゴウ,Evening Wing(Shinagawa to Misakiguchi),Evening Wing,이브닝윙호,#379412,2,2,0,,COMPLETE DEFAULT,404,普通(方南町支線),フツウ,Local(Honancho Branch Line),慢车(方南町支线),보통(호난초 지선),#E60012,0,1,0,,COMPLETE diff --git a/data/5!station_station_types.csv b/data/5!station_station_types.csv index 81344aa9..8e6d8711 100644 --- a/data/5!station_station_types.csv +++ b/data/5!station_station_types.csv @@ -41996,3 +41996,41 @@ DEFAULT,3200739,306,1186,1,上古沢 DEFAULT,3200740,306,1186,1,紀伊細川 DEFAULT,3200741,306,1186,1,紀伊神谷 DEFAULT,3200742,306,1186,0,極楽橋 +DEFAULT,2400101,413,1188,0,新宿 +DEFAULT,2400104,413,1188,1,笹塚 +DEFAULT,2400105,413,1188,1,代田橋 +DEFAULT,2400106,413,1188,0,明大前 +DEFAULT,2400107,413,1188,1,下高井戸 +DEFAULT,2400108,413,1188,1,桜上水 +DEFAULT,2400109,413,1188,1,上北沢 +DEFAULT,2400110,413,1188,1,八幡山 +DEFAULT,2400111,413,1188,1,芦花公園 +DEFAULT,2400112,413,1188,1,千歳烏山 +DEFAULT,2400113,413,1188,1,仙川 +DEFAULT,2400114,413,1188,1,つつじヶ丘 +DEFAULT,2400115,413,1188,1,柴崎 +DEFAULT,2400116,413,1188,1,国領 +DEFAULT,2400117,413,1188,1,布田 +DEFAULT,2400118,413,1188,1,調布 +DEFAULT,2400119,413,1188,1,西調布 +DEFAULT,2400120,413,1188,1,飛田給 +DEFAULT,2400121,413,1188,1,武蔵野台 +DEFAULT,2400122,413,1188,1,多磨霊園 +DEFAULT,2400123,413,1188,1,東府中 +DEFAULT,2400124,413,1188,0,府中 +DEFAULT,2400125,413,1188,0,分倍河原 +DEFAULT,2400126,413,1188,1,中河原 +DEFAULT,2400127,413,1188,0,聖蹟桜ヶ丘 +DEFAULT,2400128,413,1188,1,百草園 +DEFAULT,2400129,413,1188,0,高幡不動 +DEFAULT,2400130,413,1188,1,南平 +DEFAULT,2400131,413,1188,1,平山城址公園 +DEFAULT,2400132,413,1188,1,長沼 +DEFAULT,2400133,413,1188,0,北野 +DEFAULT,2400301,413,1188,0,北野 +DEFAULT,2400302,413,1188,1,京王片倉 +DEFAULT,2400303,413,1188,1,山田 +DEFAULT,2400304,413,1188,0,めじろ台 +DEFAULT,2400305,413,1188,1,狭間 +DEFAULT,2400306,413,1188,0,高尾 +DEFAULT,2400307,413,1188,0,高尾山口 diff --git a/data/route_service_rules.csv b/data/route_service_rules.csv index 0643f808..6068681b 100644 --- a/data/route_service_rules.csv +++ b/data/route_service_rules.csv @@ -24,3 +24,4 @@ type_cd,line_group_id,requires_timetable,boarding_wait_seconds,source,type_name, 412,1019,true,,https://www.keihan.co.jp/traffic/liner/,ライナー,京阪ライナー・平日朝夕夜限定,2026-10-13 510,,true,,https://www.keio.co.jp/zasekishitei/index_mt.html,Mt.TAKAO,土休日・少数便・方向別乗降制限,2026-10-13 519,,true,,https://www.tobu.co.jp/railway/th/timetable/,THライナー,朝夕夜限定・方向別乗降制限,2026-10-13 +413,,true,,https://www.keio.co.jp/zasekishitei/index_n.html,京王ライナー(高尾山口方面),時間帯限定・方向別乗降制限,2026-10-16 diff --git a/data_validator/tests/keio_stopping_patterns.rs b/data_validator/tests/keio_stopping_patterns.rs index a4e052cb..0d773064 100644 --- a/data_validator/tests/keio_stopping_patterns.rs +++ b/data_validator/tests/keio_stopping_patterns.rs @@ -16,7 +16,7 @@ fn sections(group: u32) -> Vec<(u32, u32, u32)> { match group { 65 | 67..=71 => vec![(24001, 1, 34)], 66 | 252 | 416 | 760..=762 => vec![(24001, 1, 18), (24002, 18, 45)], - 253 | 412..=415 | 758 | 759 => vec![(24001, 1, 33), (24003, 33, 53)], + 253 | 412..=415 | 758 | 759 | 1188 => vec![(24001, 1, 33), (24003, 33, 53)], 254 | 285..=287 | 757 => { vec![(24007, 1, 4), (24001, 4, 18), (24002, 18, 45)] } @@ -84,7 +84,7 @@ fn existing_keio_patterns_match_official_stops_and_complete_station_sequences() let audited: BTreeSet = [ 65, 66, 67, 68, 69, 70, 71, 252, 253, 254, 255, 285, 286, 287, 412, 413, 414, 415, 416, - 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, + 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 1188, ] .into_iter() .collect(); diff --git a/data_validator/tests/keio_takao_liner.rs b/data_validator/tests/keio_takao_liner.rs new file mode 100644 index 00000000..7316f68d --- /dev/null +++ b/data_validator/tests/keio_takao_liner.rs @@ -0,0 +1,57 @@ +use std::path::Path; + +use csv::StringRecord; +use stationapi::domain::service_rules::service_rule; + +fn records(path: &Path) -> Vec { + csv::Reader::from_path(path) + .unwrap() + .records() + .collect::>() + .unwrap() +} + +#[test] +fn takao_liner_has_its_own_complete_pattern_and_requires_timetable() { + let data = Path::new(env!("CARGO_MANIFEST_DIR")).join("../data"); + let types = records(&data.join("4!types.csv")); + let liner_types: Vec<_> = types.iter().filter(|r| &r[1] == "413").collect(); + assert_eq!(liner_types.len(), 1); + let liner = liner_types[0]; + assert_eq!(&liner[2], "京王ライナー(高尾山口方面)"); + assert_eq!(&liner[8], "0"); // Both directions, like the other Keio Liners. + assert_eq!(&liner[9], "2"); + + let all_rows = records(&data.join("5!station_station_types.csv")); + let rows: Vec<_> = all_rows.iter().filter(|r| &r[3] == "1188").collect(); + let expected_stations: Vec = std::iter::once(2400101) + .chain(2400104..=2400133) + .chain(2400301..=2400307) + .collect(); + let actual_stations: Vec = rows.iter().map(|r| r[1].parse().unwrap()).collect(); + assert_eq!(actual_stations, expected_stations); + + // Official up/down stopping lists, checked 2026-10-16: + // https://www.keio.co.jp/zasekishitei/ + // https://www.keio.co.jp/zasekishitei/index_n.html + // Both Kitano IDs are intentional; Katakura, Yamada and Hazama pass. + let stops = [ + 2400101, 2400106, 2400124, 2400125, 2400127, 2400129, 2400133, 2400301, 2400304, 2400306, + 2400307, + ]; + for row in rows { + let station: u32 = row[1].parse().unwrap(); + assert_eq!(&row[2], "413"); + assert_eq!( + row[4].parse::().unwrap(), + u32::from(!stops.contains(&station)) + ); + } + assert!(all_rows + .iter() + .filter(|r| &r[2] == "413") + .all(|r| &r[3] == "1188")); + let rule = service_rule(Some(413), Some(1188)).expect("Takao Liner operating rule"); + assert!(rule.requires_timetable); + assert_eq!(rule.boarding_wait_seconds, None); +} diff --git a/docs/keio-stopping-pattern-audit.md b/docs/keio-stopping-pattern-audit.md index c72aedc5..cb9c5688 100644 --- a/docs/keio-stopping-pattern-audit.md +++ b/docs/keio-stopping-pattern-audit.md @@ -26,5 +26,5 @@ - 京王八王子・高尾山口系統の特急は東府中を一部停車(`pass=5`)とし、競馬場線直通特急764は東府中の両路線IDで停車する。 - 相模原線の急行・特急、高尾線の急行・特急は各線の公式駅案内に従う。特急が高尾線内で各駅に停車しても急行の通過駅まで変更しない。 -本検査は既存の停車パターンと駅列を対象とする。新系統の収録網羅性、時刻指定検索、乗降制限の実装を保証するものではない。公式案内には高尾線の京王ライナーも掲載されているが、現行CSVには専用の路線グループがなく、系統追加は別途対応が必要。 +本検査は既存の停車パターンと駅列を対象とする。新系統の収録網羅性、時刻指定検索、乗降制限の実装を保証するものではない。監査時点で未収録だった高尾線の京王ライナーは、別PR #1724で種別413・路線グループ1188として追加する。追加後は同じ検査で新系統も照合する。 diff --git a/docs/route-service-audit.md b/docs/route-service-audit.md index 4e75fb39..3606a00a 100644 --- a/docs/route-service-audit.md +++ b/docs/route-service-audit.md @@ -21,7 +21,7 @@ S-TRAINだけでなく、登録済みの全国の種別・系統を対象に、 | --- | --- | --- | | S-TRAIN | 316・339 | [西武鉄道](https://www.seiburailway.jp/railway/reservedtrain/s-train/): 平日・土休日の別、限定時間帯、方向別乗降条件 | | 池袋発着の西武快速 | 379 / 188・620 | [公式池袋時刻表](https://seibu.ekitan.com/norikae/timetable/station/235-0/d1): 該当系統の限定便。他の快速系統は対象外 | -| 京王ライナー | 400・401 | [京王電鉄](https://www.keio.co.jp/zasekishitei/): 限定時間帯、上りの途中駅の乗降制限 | +| 京王ライナー | 400・401・413 | [京王電鉄](https://www.keio.co.jp/zasekishitei/): 限定時間帯、上りの途中駅の乗降制限 | | モーニング・イブニングウィング | 402・403 | [京急電鉄](https://www.keikyu.co.jp/ride/train/wing_detail.html): 平日朝・夕夜の片方向運転。ウィング・シート付き一般列車は対象外 | | 拝島ライナー | 405 | [西武鉄道](https://www.seiburailway.jp/railway/reservedtrain/haijimaliner/): 朝夕の限定便、方向別乗降条件 | | TJライナー | 406・407 | [東武鉄道](https://www.tobu.co.jp/railway/tj/timetable/): 上り朝、下り夕夜。快速急行341とは別種別 | @@ -55,3 +55,13 @@ S-TRAINだけでなく、登録済みの全国の種別・系統を対象に、 手動選択用の一覧には残ることを検証します。 - 通常の快速・快速急行・通勤特急が巻き込まれないことと、到達判定と探索の網が 一致することを検証します。 + +## 高尾線の京王ライナー(2026-10-16確認) + +種別413「京王ライナー(高尾山口方面)」・路線グループ1188として、新宿~高尾山口の両方向の停車パターンを登録する。 +[上りの公式停車駅・時刻表](https://www.keio.co.jp/zasekishitei/)と[下りの公式停車駅・時刻表](https://www.keio.co.jp/zasekishitei/index_n.html)を照合した。 +停車駅は新宿・明大前・府中・分倍河原・聖蹟桜ヶ丘・高幡不動・北野・めじろ台・高尾・高尾山口。北野は京王線2400133・高尾線2400301の両IDを保持する。京王片倉・山田・狭間は通過する。 + +既存の京王八王子・橋本系統と同様に方向0・kind=2を使用する。「方面」は系統を表し、下り限定ではない。Mt.TAKAO号とは独立した種別とする。上りは途中駅からの降車が明大前に限られ、運行時間帯も限定されるため、requires_timetable=trueを登録し、時刻を扱わないconnectedRoutes・到達可能性検索には採用しない。手動の種別選択・経路表示用の停車パターンとして提供する。 + +`cargo test -p data_validator --test keio_takao_liner` は種別メタデータ・全38行の駅順・全停車/通過・北野両ID・時刻表必須ルールを検査する。