駅リスト始点からの予定到着時間(分数)推定ロジックを追加 - #1563
Conversation
公式時刻表・商用API・実距離データが無い制約のもと、駅座標(haversine 直線距離)と メタデータのみから、経路始点から各駅までの累積到着時間(分)を推定する純粋ロジックを domain/arrival_estimation.rs に追加。 - 直線距離を迂回係数 α で軌道距離へ補正(α は Line.average_distance(実距離±10%精度) で line_cd ごとに較正し、無い線は路線種別ベースの固定値にフォールバック) - 停車駅間の走行時間を「加速→巡航→減速」の運動学モデルで算出(停車が多いほど遅くなる 現象を加減速ペナルティとして自然に表現) - 列車種別の通過/停車パターン(pass / stop_condition)を考慮、通過駅は距離比で補間 - 経路は line_group_cd を跨がない(単一直通サービス)前提のため乗換時間は加算しない - QueryUseCase::estimate_route_arrival_times を追加し、既存の get_route_stops / build_route_tree_map を再利用して結線 - query.rs の重複 haversine_distance をドメイン実装へ委譲 - 純粋アルゴリズムの単体テストと interactor 統合テストを追加 クライアントへの gRPC 公開には外部 submodule(gRPCProto)の proto 変更が必要なため、 本コミットでは内部ロジックとして実装し、公開は別途 Issue で追跡する。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011x2mHWsf7bhqH1THoWg3gJ
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 Walkthroughウォークスルー
変更内容経路到着時刻推定機能
推定コードレビュー工数🎯 4 (Complex) | ⏱️ ~60 minutes 関連する可能性のある Issue
提案ラベル
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption. Comment |
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011x2mHWsf7bhqH1THoWg3gJ
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
stationapi/src/use_case/interactor/query.rs (1)
2238-2265: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win複数経路ケースの回帰テストも欲しいです。
このテストは単一
line_group_cdしか通らないため、Line 1035-1044 の group 絞り込み漏れと Line 1041-1043 の順序揺れを検出できません。2 経路以上を返すケースで件数と連結順まで固定しておくと、今回の配線変更をかなり守れます。🤖 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/use_case/interactor/query.rs` around lines 2238 - 2265, Add a regression test alongside test_estimate_route_arrival_times_through_service_and_pass that exercises estimate_route_arrival_times with multiple route candidates, not just a single line_group_cd. Use build_interactor and create_geo_stop to construct a case where more than one group is returned, then assert both the expected count and the exact concatenation/order of the resulting path so group filtering and ordering regressions are caught.
🤖 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/domain/arrival_estimation.rs`:
- Around line 272-285: The `arrival_estimation` logic is collapsing a
multi-segment pass-through stretch into one `v_max`, so speed changes across
`line_cd` / `line_type` / `kind` are not reflected. Update the segment
accumulation in `segment_run_minutes` handling so `stops_here` processing splits
the pending run at each profile boundary, computes travel time per subsegment
using the appropriate speed for that portion, and then accumulates
`cumulative_minutes` for each pending stop by segment rather than applying a
single end-stop-based `v_max` to the whole distance. Preserve the existing
`result` update flow, but base it on per-speed-profile chunks instead of one
distance-ratio interpolation.
In `@stationapi/src/use_case/interactor/query.rs`:
- Around line 1041-1043: The Vec<EstimatedStop> order is currently unstable
because Query::build_route_tree_map output is concatenated via
route_row_tree_map.iter() in arbitrary HashMap order. Update the aggregation in
the query flow to collect the line_group_cd keys, sort them deterministically,
and then extend results in that sorted order using estimate_arrival_minutes so
the API response order is stable. Recheck build_route_tree_map and the
surrounding query logic to ensure the flattened return value preserves a
consistent contract.
- Around line 1035-1044: `build_route_tree_map` の後に候補 group をそのまま
`estimate_arrival_minutes` に流しているため、`get_routes` / `get_routes_minimal`
と同様の絞り込みが抜けて無関係な経路が混ざります。`query.rs` 内の既存の group चयनロジックを共通化し、このメソッドでも同じ条件で
`route_row_tree_map` をフィルタしてから `result.extend(...)`
するように修正してください。`get_routes`、`get_routes_minimal`、`build_route_tree_map`、`estimate_arrival_minutes`
を目印に、重複した判定は共通関数へ寄せて再利用してください。
In `@stationapi/src/use_case/traits/query.rs`:
- Around line 126-134: The return contract of estimate_route_arrival_times in
QueryUseCase cannot represent route boundaries because it flattens multiple
line_group_cd routes into a single Vec of EstimatedStop, so callers cannot
reliably tell where one route ends and the next begins. Update the trait and its
implementation in QueryInteractor::estimate_route_arrival_times to return
route-grouped results (nested per route) or add a route identifier to each
EstimatedStop so each segment can be distinguished. Make sure the new shape
preserves the line_group_cd grouping currently assembled in the query
interactor.
---
Nitpick comments:
In `@stationapi/src/use_case/interactor/query.rs`:
- Around line 2238-2265: Add a regression test alongside
test_estimate_route_arrival_times_through_service_and_pass that exercises
estimate_route_arrival_times with multiple route candidates, not just a single
line_group_cd. Use build_interactor and create_geo_stop to construct a case
where more than one group is returned, then assert both the expected count and
the exact concatenation/order of the resulting path so group filtering and
ordering regressions are caught.
🪄 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: aae78145-4661-4d55-b2f0-7db6a6987d42
📒 Files selected for processing (5)
stationapi/src/domain.rsstationapi/src/domain/arrival_estimation.rsstationapi/src/presentation/controller/grpc.rsstationapi/src/use_case/interactor/query.rsstationapi/src/use_case/traits/query.rs
- estimate_route_arrival_times で、要求された駅(始点・終点)を含まない候補 line_group を get_routes / get_routes_minimal と同様に除外する - EstimatedStop に line_group_cd を追加し、複数候補経路をフラットな Vec で返す際に 呼び出し側が経路境界を復元できるようにする - 停車駅間を速度プロファイル(line_cd / line_type / kind)別のサブ区間に分割し、 直通で速度が変わる区間の走行時間を区間ごとに積み上げるよう運動学モデルを改良 (単一サブ区間は従来どおり加減速込みの厳密計算、短区間は三角形プロファイル) - 複数候補経路のフィルタ・連結順(line_group_cd 昇順)・経路識別子を検証する 回帰テストと、速度分割を検証する単体テストを追加 なお build_route_tree_map は BTreeMap を返すため連結順は元々決定的(HashMap 順依存 の指摘は該当せず)。コメントで明示。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011x2mHWsf7bhqH1THoWg3gJ
|
@coderabbitai レビューありがとうございます。
なお 結果順が HashMap 走査順に依存(query.rs L1043) のご指摘については、 Generated by Claude Code |
|
Tip For best results, initiate chat on the files or code changes.
候補 group のフィルタ追加、 ありがとうございます、こちらは解消と認識します。 ✏️ Learnings added
|
概要
公式時刻表・商用API・実距離データが無い制約のもと、駅座標(haversine 直線距離)とメタデータだけから、経路始点から各駅までの予定到着時間(始点からの累積分数)を推定する純粋ロジックを追加します。
変更の種類
変更内容
stationapi/src/domain/arrival_estimation.rsを新規追加(IO を持たない純粋ロジック)。推定モデル:αで「みなし走行距離(軌道距離)」へ補正。αはLine.average_distance(実距離±10%精度)でline_cdごとにclamp(average_distance / 直線平均, 1.0, 1.6)と較正し、得られない線は路線種別ベースの固定値(新幹線 1.15 / 在来線 1.30 / 地下鉄等 1.40)にフォールバック。pass/stop_condition)を考慮。通過駅は区間内の距離比で通過時刻を線形補間。中間停車駅に停車時間dwellを加算して累積。line_group_cdを跨がない(単一の直通サービス)前提のため乗換時間は加算しない。複数line_cdはα・最高速度の切り替えにのみ使用。QueryUseCase::estimate_route_arrival_timesを追加し、既存のget_route_stops/build_route_tree_mapを再利用して結線。query.rsに重複していたhaversine_distanceをドメイン実装へ委譲し一本化。クライアントへの gRPC 公開には外部 submodule
TrainLCD/gRPCProtoの proto 変更が必要なため、本 PR では内部ロジックとして実装し、公開は別途 Issue で追跡します(下記 関連Issue)。テスト
cargo fmt --all -- --checkが通ることcargo clippy -- -D warningsが通ることcargo test(SQLX_OFFLINE=true)が通ること関連Issue
Refs #1562
スクリーンショット(任意)
Generated by Claude Code
Summary by CodeRabbit