Skip to content

東急バスをGTFS・ODPT JSONから統合#1600

Merged
TinyKitten merged 3 commits into
devfrom
feature/tokyu-bus-integration
Jul 12, 2026
Merged

東急バスをGTFS・ODPT JSONから統合#1600
TinyKitten merged 3 commits into
devfrom
feature/tokyu-bus-integration

Conversation

@TinyKitten

@TinyKitten TinyKitten commented Jul 12, 2026

Copy link
Copy Markdown
Member

概要

東急バスを StationAPI に統合する。大田区・品川区・目黒区のコミュニティバスは公式 GTFS フィードから、東急バスの一般路線は ODPT の JSON API (BusroutePattern / BusstopPole / BusTimetable) を GTFS 相当の表現へ変換して取り込む。

変更の種類

  • バグ修正
  • 新機能
  • データの修正・追加
  • リファクタリング
  • ドキュメント
  • CI/CD
  • その他

変更内容

  • stationapi/src/import.rs:
    • 東急バス運行のコミュニティバス GTFS 3 フィード(大田区たまちゃんバス・品川区しなバス・目黒区さんまバス)を GTFS_FEEDS に追加。URL は date=currentODPT_ACCESS_TOKEN 必須。
    • 東急バス一般路線の ODPT JSON(BusroutePattern / BusstopPole / BusTimetable)をダウンロードし、gtfs_* テーブルへ変換して取り込む import_tokyu_odpt_data() を追加。パターン ID を shape_id として扱い、路線バリエーションをバス TrainType として保持。
    • ODPT JSON は全事業者分の巨大配列を返すため、レスポンスをファイルへストリーミングしつつ DeserializeSeed で東急バス分のみ抽出し、7 日間キャッシュを data/TokyuBus-ODPT/ に保存。
    • コミュニティバス(Tamachan / Shinabasu / Sanma)は公式 GTFS を使用し、JSON 側の同一路線を除外して重複を防止。
    • HH:MM 形式の ODPT 時刻を GTFS の HH:MM:SS へ整える parse_odpt_time() を追加。
    • company_cd_for_gtfs_route()tokyu_ プレフィックス(company_cd=254)を追加。
    • クエリ文字列付き URL にトークンを安全に連結する gtfs_download_url_with_token() を追加。
    • 上記に対応するユニットテストを追加。
  • data/1!companies.csv: company_cd=254 東急バス(東急バス株式会社)を追加。
  • stationapi/Cargo.toml / Cargo.lock: reqwestgzip feature を追加(async-compression 依存を追加)。
  • .gitignore: 東急バス関連の GTFS / キャッシュディレクトリを追加。
  • AGENTS.md / docs/architecture.md / README.md: 東急バス統合とデータ提供元の記載を追記。

テスト

  • cargo fmt --all -- --check が通ること
  • cargo clippy -- -D warnings が通ること
  • cargo testSQLX_OFFLINE=true)が通ること

SQLX_OFFLINE=true cargo test は 35 passed / 0 failed。データ変更を含むため cargo run -p data_validator も実行し [VALID] No errors reported. を確認。

関連Issue

スクリーンショット(任意)

Summary by CodeRabbit

  • 新機能
    • 東急バス(一般路線)データに対応しました。
    • 大田区・品川区・目黒区のコミュニティバスを追加しました。
    • 鉄道とバスを統合した検索で、東急バスを含む路線・停留所を利用できます。
    • 座標がない停留所も名称・路線検索の対象になりました。
  • ドキュメント
    • 対応データ提供元、取り込み手順、前提条件(認証トークンの対象など)を更新しました。
  • メンテナンス
    • GTFSデータの無視対象を追加しました。

大田区・品川区・目黒区のコミュニティバスGTFSと、東急バス一般路線の
ODPT JSON (BusroutePattern/BusstopPole/BusTimetable) をGTFS相当へ変換して統合。
company_cd=254 東急バスを追加。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@TinyKitten TinyKitten self-assigned this Jul 12, 2026
@github-actions github-actions Bot added feature 要望対応や課題解決 deploy-dev labels Jul 12, 2026
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 10 seconds

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4682c94e-ab86-47de-b3bd-ddcd1b6afdce

📥 Commits

Reviewing files that changed from the base of the PR and between 8a4ef6d and a141da2.

⛔ Files ignored due to path filters (1)
  • data/1!companies.csv is excluded by !**/*.csv
📒 Files selected for processing (5)
  • .gitignore
  • AGENTS.md
  • README.md
  • docs/architecture.md
  • stationapi/src/import.rs
📝 Walkthrough

Walkthrough

東急バスのODPT JSONを取得・キャッシュし、GTFS相当のデータへ変換して既存テーブルへ投入する処理を追加しました。認証付きURL、gzip対応、会社コード、コミュニティ路線除外、関連ドキュメントも更新しています。

Changes

東急バスデータ統合

Layer / File(s) Summary
ODPT取得と選別
stationapi/src/import.rs, stationapi/Cargo.toml
gzip対応のHTTPクライアントで認証付きODPT JSONを取得し、Tokyu運行データだけをストリーミング抽出してキャッシュします。
GTFS投影と会社マッピング
stationapi/src/import.rs
ODPTのpatterns、stops、timetablesをGTFSテーブルへ変換・投入し、時刻変換、座標欠落の警告、コミュニティ路線除外、Tokyuの会社コード254を処理します。関連するテストも追加・更新しています。
取り込み設定と運用記録
.gitignore, AGENTS.md, README.md, docs/architecture.md
認証対象、データソース、キャッシュ、バス統合の処理仕様、生成データの除外対象を記録しています。

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant import_gtfs
  participant ODPT
  participant TokyuCache
  participant gtfs_tables
  import_gtfs->>ODPT: Tokyu Bus JSONを取得
  ODPT-->>import_gtfs: patterns/stops/timetables
  import_gtfs->>TokyuCache: Tokyuデータをキャッシュ
  import_gtfs->>gtfs_tables: agencies/routes/stops/trips/stop_timesを投入
  gtfs_tables-->>import_gtfs: 取り込み完了
Loading

Possibly related PRs

Poem

にんじん片手にバスを追う
ODPTの道をぴょんと跳ぶ
GTFSの席へデータを運び
Tokyuの路線が仲間入り
うさぎも時刻表にっこり 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 51.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 変更内容の中心である東急バスのGTFS/ODPT統合を簡潔に表しており、タイトルとして適切です。
Description check ✅ Passed テンプレートの主要セクションが揃っており、概要・変更内容・テスト・関連Issueの構成も満たしています。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/tokyu-bus-integration

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
stationapi/src/import.rs (2)

933-961: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

insert_tokyu_stop_values は手動エスケープした文字列連結でSQLを構築しています。sqlx::QueryBuilder を使ったバインドパラメータ方式のほうが安全です。

escape_sql_string によるエスケープはテストされていますが、複数値INSERTを毎回文字列フォーマットで組み立てる方式は、将来のカラム追加やエスケープ漏れに弱い構造です。sqlx::QueryBuilder::push_values を使えば型安全なバインドで同等のバルクINSERTが実現できます。

♻️ 提案: QueryBuilderでバルクINSERT
let mut qb = sqlx::QueryBuilder::new(
    "INSERT INTO gtfs_stops (stop_id, stop_code, stop_name, stop_name_k, stop_name_r, stop_lat, stop_lon) ",
);
qb.push_values(rows, |mut b, (stop_id, code, name, name_k, lat, lon)| {
    b.push_bind(stop_id)
        .push_bind(code)
        .push_bind(name)
        .push_bind(name_k)
        .push_bind(None::<String>)
        .push_bind(lat)
        .push_bind(lon);
});
qb.push(" ON CONFLICT (stop_id) DO NOTHING");
qb.build().execute(&mut *conn).await?;

Also applies to: 1063-1077

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@stationapi/src/import.rs` around lines 933 - 961, Replace the manual SQL
string construction used by insert_tokyu_stop_values with
sqlx::QueryBuilder::push_values and bound parameters for every stop column,
retaining the existing bulk batching and ON CONFLICT behavior. Update the
corresponding stop insertion flow at the additional location as well, and remove
reliance on escape_sql_string for these inserts.

488-554: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

キャッシュディレクトリの解決方法がコンパイル時パスに依存しており、実行環境によって破綻するリスクがあります。

env!("CARGO_MANIFEST_DIR") はコンパイル時にビルド環境の絶対パスを埋め込むマクロです。一方、同ファイル内の他のGTFSフィード (data/ToeiBus-GTFS など、download_gtfs) は実行時のカレントディレクトリからの相対パスで解決しています。ビルド環境と実行環境のファイルシステムレイアウトが異なる場合(例: マルチステージDockerビルドでバイナリだけを別イメージにコピーする構成へ将来変更した場合など)、cache_dir がビルド時の絶対パスを指し続け、fs::metadata/fs::create_dir_all が失敗する可能性があります。他のフィードと同様に実行時カレントディレクトリ相対のパスに統一することを推奨します。

♻️ 提案: 他フィードと同様に実行時相対パスに統一
-    let cache_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("../data/TokyuBus-ODPT");
+    let cache_dir = Path::new("data/TokyuBus-ODPT");

現在のDocker構成(docker/api/Dockerfile が同一イメージ内で cargo builddata/ コピーを行う想定)では問題にならない可能性がありますが、将来のビルド構成変更に対して脆弱です。Dockerfileの実際の構成を確認いただけますか。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@stationapi/src/import.rs` around lines 488 - 554, Update the cache_dir
initialization in download_odpt_json to resolve TokyuBus-ODPT from the runtime
current working directory, matching the relative-path behavior used by
download_gtfs and the other GTFS feeds. Remove the compile-time
env!("CARGO_MANIFEST_DIR") dependency while preserving the existing cache read
and write flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@stationapi/src/import.rs`:
- Around line 916-929: Update the gtfs_routes INSERT in the inserted_routes
block to bind route_long_name_r separately from route_long_name_r, storing NULL
for route_long_name_r because tokyu_route_name returns Japanese text. In
insert_tokyu_stop_values, likewise store NULL in stop_name_r instead of
stop.title, while preserving the Japanese values in the non-_r name columns and
existing fallback behavior.

---

Nitpick comments:
In `@stationapi/src/import.rs`:
- Around line 933-961: Replace the manual SQL string construction used by
insert_tokyu_stop_values with sqlx::QueryBuilder::push_values and bound
parameters for every stop column, retaining the existing bulk batching and ON
CONFLICT behavior. Update the corresponding stop insertion flow at the
additional location as well, and remove reliance on escape_sql_string for these
inserts.
- Around line 488-554: Update the cache_dir initialization in download_odpt_json
to resolve TokyuBus-ODPT from the runtime current working directory, matching
the relative-path behavior used by download_gtfs and the other GTFS feeds.
Remove the compile-time env!("CARGO_MANIFEST_DIR") dependency while preserving
the existing cache read and write flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f74c6699-78a6-4a8c-871f-9f1eee2cb166

📥 Commits

Reviewing files that changed from the base of the PR and between e732749 and 0c0638c.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • data/1!companies.csv is excluded by !**/*.csv
📒 Files selected for processing (6)
  • .gitignore
  • AGENTS.md
  • README.md
  • docs/architecture.md
  • stationapi/Cargo.toml
  • stationapi/src/import.rs

Comment thread stationapi/src/import.rs
@TinyKitten

Copy link
Copy Markdown
Member Author

Fixes Applied Successfully

Fixed 1 file(s) based on 1 CodeRabbit feedback item(s).

Files modified:

  • stationapi/src/import.rs

Fix: route_long_name_r / stop_name_r はローマ字/英語のフォールバック契約に反して日本語を格納していたため、ローマ字情報を持たない ODPT JSON 由来のこれらの列を NULL に修正(下流の type_name_r フォールバックに委譲)。

Commit: 8a4ef6d

The latest autofix changes are on the feature/tokyu-bus-integration branch.

devに先行マージされた京王バスGTFS統合(#1601, #1602)と東急バス統合の
コンフリクトを解消。

- data/1!companies.csv / import.rs: 京王バスがcompany_cd=254を先に取得済み
  のため、東急バスをcompany_cd=254から255へ振り直して衝突を回避
  (company_cd_for_gtfs_route・gtfs_agencies INSERT・関連テストを更新)
- import.rs: トークン付与ヘルパーを両ブランチ重複追加していたため、
  devのappend_consumer_key(url, token)に統一しgtfs_download_url_with_token
  を削除。呼び出し箇所とテストを追従
- GTFS_FEEDS: 東急コミュニティバス3フィードと京王バスの両方を保持
- .gitignore / AGENTS.md / README.md / docs/architecture.md:
  両ブランチのバス統合記述・データ提供元・無視対象を統合

検証: cargo fmt --check / cargo clippy -D warnings / cargo test
(SQLX_OFFLINE=true, 36 passed) / cargo run -p data_validator ([VALID]) 通過

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UNY8jqgNN2xpnRSrK758h8
@TinyKitten

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@TinyKitten TinyKitten merged commit 25851ac into dev Jul 12, 2026
19 checks passed
@TinyKitten TinyKitten deleted the feature/tokyu-bus-integration branch July 12, 2026 09:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

deploy-dev feature 要望対応や課題解決

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants