-
-
Notifications
You must be signed in to change notification settings - Fork 3
バス経路に時刻表ベースのstop_conditionフィルタリングを追加 #1383
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- get_routes/get_routes_minimalにバス時刻表フィルタリングを実装 - 現在のJST時刻で±30分以内に発車予定がないバス停は stop_condition=Notを返すように変更 - StationRepositoryにget_active_bus_stop_station_cdsメソッドを追加 - gtfs_calendar/gtfs_calendar_datesを使用して曜日別の サービス運行状況を考慮 - ユニットテストを追加(get_current_jst、バス停判定など)
📝 WalkthroughWalkthroughStationRepository にバス停の「アクティブ」判定を行う非同期メソッドを追加し、インフラでGTFSベースのSQL実装を導入。ユースケースで JST 時刻算出を追加して取得結果に基づくバス停フィルタを適用、GTFS stop_id の永続化と関連テストを追加。 Changes
Sequence DiagramsequenceDiagram
participant Client
participant UseCase as Use Case
participant Repo as StationRepository
participant DB as GTFS_DB
Client->>UseCase: ルート/駅情報要求
UseCase->>UseCase: get_current_jst() を計算(YYYYMMDD, HH:MM:SS)
Note over UseCase: 対象の bus stop station_cds を収集
UseCase->>Repo: get_active_bus_stop_station_cds(station_cds, time, date)
Repo->>DB: 実行(SQL: services by weekday/calendar → stop_times ±30min → stations.gtfs_stop_id join)
DB-->>Repo: アクティブな station_cds の集合
Repo-->>UseCase: HashSet<station_cd>
UseCase->>UseCase: 非アクティブは stop_condition = Not に設定
UseCase-->>Client: フィルタ済み結果を返却
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
get_routes/get_routes_minimal以外のAPIエンドポイントにも バス時刻表フィルタリングを適用 対象メソッド: - get_station_by_id - get_stations_by_id_vec - get_stations_by_group_id - get_stations_by_coordinates - get_stations_by_line_id - get_stations_by_name - get_stations_by_line_group_id
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@stationapi/src/domain/repository/station_repository.rs`:
- Around line 90-94: フォーマットエラーが出ているのでリポジトリの Rust コードを整形してください:
station_repository.rs 内のテストデータ追加ブロック(create_test_bus_stop と stations.insert
を使っている箇所)を含めて、プロジェクトルートで cd stationapi && cargo fmt --all
を実行して自動整形し、フォーマット差分をコミットしてください(CI 用には cargo fmt --all -- --check
をローカルで確認してからコミットすること)。
In `@stationapi/src/infrastructure/station_repository.rs`:
- Around line 1572-1599: Run rustfmt (cargo fmt) to fix formatting issues in the
time-window calculation block that defines current_time_jst, time_parts, hours,
minutes, total_minutes, start_minutes, end_minutes, start_time and end_time;
ensure spacing, line breaks, and alignment follow rustfmt rules (e.g.,
consistent indentation and wrapping for the chained parse/unwrap_or calls and
the format! macros) and commit the formatted file.
- Around line 1650-1663: Format error around the HashSet construction should be
fixed by running rustfmt; from the repository root run the suggested command (cd
stationapi && cargo fmt --all) to reformat code where StationCdRow/rows/result
are defined, then commit the changes so the block that builds result:
std::collections::HashSet<i32> using rows.into_iter().filter_map(|r|
r.station_cd).collect() is properly formatted.
In `@stationapi/src/use_case/interactor/query.rs`:
- Around line 667-721: The file has formatting issues detected by CI; run
rustfmt/cargo fmt and reformat the changes around the block that constructs
proto_station (references: tt_line_map, TrainType creation,
build_station_from_row, proto::StopCondition) so the if/else indentation and
method chains (tt_lines.iter().filter(...).cloned().collect()) conform to
rustfmt style; after running cargo fmt, stage the updated file and push the
formatted changes.
🧹 Nitpick comments (2)
stationapi/src/use_case/interactor/query.rs (2)
753-769:get_routesとget_routes_minimalでバス停フィルタリングロジックが重複しています。同じロジックが2箇所にあるため、将来的にはヘルパーメソッドに抽出することを検討してください。現時点では動作に問題はありませんが、保守性の観点から改善の余地があります。
♻️ ヘルパーメソッド抽出の例
async fn get_active_bus_stops_for_route(&self, stops: &[Station]) -> HashSet<i32> { let bus_station_cds: Vec<i32> = stops .iter() .filter(|s| s.transport_type == TransportType::Bus) .map(|s| s.station_cd) .collect(); if bus_station_cds.is_empty() { return HashSet::new(); } let (current_date, current_time) = get_current_jst(); self.station_repository .get_active_bus_stop_station_cds(&bus_station_cds, ¤t_time, ¤t_date) .await .unwrap_or_default() }
6-14:chrono::TimeDelta::hoursの使用を推奨します。
chrono::Duration::hoursは現在のバージョンで正式には非推奨ではありませんが、最新のchronoではより推奨されるアプローチはchrono::TimeDelta::hoursを使用することです。将来のバージョン互換性のため、Duration::hours(9)をTimeDelta::hours(9)に置き換えることを検討してください。また、この関数はテスト時にモック化が困難です。将来的に、時刻をパラメータとして受け取る設計(例:
fn get_current_jst(now: DateTime<Utc>) -> (String, String))も検討できます。
鉄道駅の近くにあるバス路線(nearby_bus_lines)に含まれる バス停についても時刻表フィルタリングを適用 - nearby_bus_linesを事前に収集し、バス停station_cdを含める - 一度のget_active_bus_stop_station_cds呼び出しで すべてのバス停の運行状況を取得 - 運行していないバス停のstop_conditionをNotに設定
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@stationapi/src/use_case/interactor/query.rs`:
- Around line 318-326: 呼び出し元で .unwrap_or_default() によって
get_active_bus_stop_station_cds
のエラーを飲み込んでいるため、失敗時に何が起きたか分からなくなっています。active_bus_stops を生成する箇所で
station_repository.get_active_bus_stop_station_cds(...) の結果を match して Err(_)
の場合は適切なロガー(例: tracing::error! または
self.logger.error)でエラー内容を出力し、続けて安全なデフォルト(HashSet::new())を返すように修正してください;参照箇所:
get_active_bus_stop_station_cds, active_bus_stops,
station_repository(get_current_jst 呼び出しはそのまま利用)。
- Around line 877-884: The stop_condition computation is inconsistent between
get_routes and get_routes_minimal: update get_routes_minimal to use
row.stop_condition (converted from the StopCondition enum) instead of row.pass
so both functions derive stop_condition from the same source; specifically, in
get_routes_minimal replace the current logic that uses row.pass with logic
equivalent to get_routes (use row.stop_condition as i32, but still override to
proto::StopCondition::Not as i32 when row.transport_type == TransportType::Bus
&& !active_bus_stops.contains(&row.station_cd)). Ensure you reference the same
fields (row.stop_condition, TransportType::Bus, active_bus_stops, and
proto::StopCondition::Not) and keep the conversion to i32 consistent with
get_routes.
♻️ Duplicate comments (1)
stationapi/src/use_case/interactor/query.rs (1)
719-773: フォーマットの問題を修正してください。パイプラインでフォーマットエラーが検出されています。
cargo fmtを実行してください。
🧹 Nitpick comments (3)
stationapi/src/use_case/interactor/query.rs (3)
289-326: バス停フィルタリングロジックの重複があります。同じパターンが3箇所(
update_station_vec_with_attributes、get_routes、get_routes_minimal)で繰り返されています。ヘルパーメソッドへの抽出を検討してください。♻️ リファクタリング案
/// Helper to get active bus stops from a list of stations async fn get_active_bus_stops_for_stations( &self, stations: &[Station], ) -> HashSet<i32> { let bus_station_cds: Vec<i32> = stations .iter() .filter(|s| s.transport_type == TransportType::Bus) .map(|s| s.station_cd) .collect(); if bus_station_cds.is_empty() { return HashSet::new(); } let (current_date, current_time) = get_current_jst(); self.station_repository .get_active_bus_stop_station_cds(&bus_station_cds, ¤t_time, ¤t_date) .await .unwrap_or_else(|e| { tracing::warn!("Failed to get active bus stops: {}", e); HashSet::new() }) }Also applies to: 674-690, 805-821
721-755:matchをifに置き換えることで可読性が向上します。
match row.type_id.is_some()はif let Some(_) = row.type_idまたは単純なif row.type_id.is_some()に書き換えることで、より自然なRustイディオムになります。♻️ リファクタリング案
- let train_type = match row.type_id.is_some() { - true => { + let train_type = if row.type_id.is_some() { // Filter lines to only include those with matching line_group_cd // and remove duplicates by line_cd let mut seen_line_cds = std::collections::HashSet::new(); let filtered_lines: Vec<Line> = tt_lines .iter() .filter(|line| { row.line_group_cd.is_some() && line.line_group_cd == row.line_group_cd && seen_line_cds.insert(line.line_cd) }) .cloned() .collect(); Some(Box::new(TrainType { id: row.type_id, station_cd: Some(row.station_cd), type_cd: row.type_cd, line_group_cd: row.line_group_cd, pass: row.pass, type_name: row.type_name.clone().unwrap_or_default(), type_name_k: row.type_name_k.clone().unwrap_or_default(), type_name_r: row.type_name_r.clone(), type_name_zh: row.type_name_zh.clone(), type_name_ko: row.type_name_ko.clone(), color: row.color.clone().unwrap_or_default(), direction: row.direction, kind: row.kind, line: Some(Box::new(tt_line.clone())), lines: filtered_lines, })) - } - false => None, - }; + } else { + None + };
6-14: 関数内のuse文をファイル先頭のインポートに統合することを検討してください。
chrono::Duration::hours()は現在サポートされているバージョン(0.4.20+)で動作しますが、chrono 0.4.26 以降ではDurationはTimeDeltaの型エイリアスとなっています。最新のベストプラクティスに従うため、TimeDelta::hours()を使用する方が望ましいです。ただし、現在のコードは機能的には問題ありません。
- get_active_bus_stop_station_cdsのエラー時にtracing::warnでログ出力 - get_routes_minimalでrow.passではなくrow.stop_conditionを使用し get_routesとの一貫性を確保
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@stationapi/src/use_case/interactor/query.rs`:
- Around line 6-14: The get_current_jst function imports and uses
chrono::Duration which is being renamed to chrono::TimeDelta; update the import
and usage to avoid deprecation: replace use chrono::{Duration, Utc}; with use
chrono::{TimeDelta, Utc}; and change Duration::hours(9) to TimeDelta::hours(9)
inside get_current_jst so the code uses TimeDelta::hours(9) when computing
jst_now.
🧹 Nitpick comments (1)
stationapi/src/use_case/interactor/query.rs (1)
684-710: アクティブバス停取得ロジックの重複を検討してください。
get_active_bus_stop_station_cdsの呼び出しパターンがupdate_station_vec_with_attributes、get_routes、get_routes_minimalの3箇所で重複しています。ヘルパーメソッドへの抽出を検討できますが、各呼び出し箇所で微妙にコンテキストが異なるため、現状のままでも問題ありません。♻️ ヘルパーメソッド抽出の例
async fn get_active_bus_stops_for_stations( &self, bus_station_cds: &[i32], ) -> HashSet<i32> { if bus_station_cds.is_empty() { return HashSet::new(); } let (current_date, current_time) = get_current_jst(); match self .station_repository .get_active_bus_stop_station_cds(bus_station_cds, ¤t_time, ¤t_date) .await { Ok(stops) => stops, Err(e) => { tracing::warn!( "Failed to get active bus stop station_cds: {}. Using empty set as fallback.", e ); HashSet::new() } } }
chrono::Durationは非推奨のため、TimeDeltaを使用するように変更
TimeDelta::hours()がOption<TimeDelta>を返すようになったため、 FixedOffset::east_opt()を使用した正しいタイムゾーン変換に変更
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@stationapi/src/use_case/interactor/query.rs`:
- Around line 338-345: The new bus-stop filtering only updates the top-level
station.stop_condition, causing station.lines[*].station.stop_condition to stay
stale; update the same Not-setting logic for the nested copy used for lines (the
variable named station_copy or similar) whenever station.transport_type ==
TransportType::Bus and station.station_cd is not in active_bus_stops so that
both station.stop_condition and station_copy.lines[i].station.stop_condition are
set to crate::proto::StopCondition::Not; locate the loop over stations
(function/query handling where stations.iter_mut() is used) and apply the
identical conditional assignment to the nested station copy used for lines to
keep display state consistent.
update_station_vec_with_attributes内でlines配列に設定される ネストされたstation_copyにもバス時刻表フィルタリングを適用し、 トップレベルのstation.stop_conditionと一貫性を保つ
- station_repository.rsにuse chrono::Datelike;を追加してweekday()メソッドを使用可能に - create_test_bus_stop()にkindパラメータを追加 - test_get_by_line_group_idの期待値を4から6に更新(バス停を含む)
active_bus_stopsが空の場合(バス運行時間外)はフィルタリングをスキップし、 元のstop_conditionを維持するように変更。
問題: 同じバス停が各路線ごとに異なるstation_cdを持つため、 gtfs_stops.station_cdとのマッピングが正しく機能していなかった。 解決策: - stationsテーブルにgtfs_stop_idカラムを追加 - インポート処理でgtfs_stop_idを設定 - SQLクエリをgtfs_stop_id経由でJOINするように変更 - 親バス停と子バス停(ポール)の両方に対応
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@stationapi/src/use_case/interactor/query.rs`:
- Around line 290-349: The code currently treats an error and a genuine empty
result identically for active_bus_stops, causing "no filter" behavior when there
are actually zero departures; change active_bus_stops from a HashSet to an
Option<HashSet<i32>> so that on Ok(stops) you return Some(stops) (including
Some(empty) for zero results) and on Err(e) you return None (and log the error)
— adjust consumers of active_bus_stops accordingly to apply the filter when
Option::Some is present and skip filtering only when None; update the match
around station_repository.get_active_bus_stop_station_cds, the variable
declaration for active_bus_stops, and any uses in
update_station_vec_with_attributes / related get_routes/get_routes_minimal flows
to follow this semantics.
| // Collect all bus stop station_cds for timetable filtering | ||
| let mut bus_station_cds: Vec<i32> = stations | ||
| .iter() | ||
| .filter(|s| s.transport_type == TransportType::Bus) | ||
| .map(|s| s.station_cd) | ||
| .collect(); | ||
|
|
||
| // For RailAndBus, also collect nearby bus stops from rail stations | ||
| let should_include_bus_routes = transport_type == TransportTypeFilter::RailAndBus; | ||
| let mut nearby_bus_lines_map: std::collections::HashMap<i32, Vec<Line>> = | ||
| std::collections::HashMap::new(); | ||
|
|
||
| if should_include_bus_routes { | ||
| for station in stations.iter() { | ||
| if station.transport_type == TransportType::Rail { | ||
| let nearby_bus_lines = | ||
| self.get_nearby_bus_lines(station.lat, station.lon).await?; | ||
| // Collect bus stop station_cds from nearby bus lines | ||
| for bus_line in &nearby_bus_lines { | ||
| if let Some(ref bus_stop) = bus_line.station { | ||
| bus_station_cds.push(bus_stop.station_cd); | ||
| } | ||
| } | ||
| nearby_bus_lines_map.insert(station.station_cd, nearby_bus_lines); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Get active bus stops based on current JST time | ||
| let active_bus_stops = if !bus_station_cds.is_empty() { | ||
| let (current_date, current_time) = get_current_jst(); | ||
| tracing::debug!( | ||
| "update_station_vec_with_attributes: bus_station_cds.len()={}, date={}, time={}", | ||
| bus_station_cds.len(), | ||
| current_date, | ||
| current_time | ||
| ); | ||
| match self | ||
| .station_repository | ||
| .get_active_bus_stop_station_cds(&bus_station_cds, ¤t_time, ¤t_date) | ||
| .await | ||
| { | ||
| Ok(stops) => { | ||
| tracing::debug!( | ||
| "update_station_vec_with_attributes: active_bus_stops.len()={}", | ||
| stops.len() | ||
| ); | ||
| stops | ||
| } | ||
| Err(e) => { | ||
| tracing::warn!( | ||
| "Failed to get active bus stop station_cds: {}. Using empty set as fallback.", | ||
| e | ||
| ); | ||
| HashSet::new() | ||
| } | ||
| } | ||
| } else { | ||
| HashSet::new() | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
active_bus_stops が空のときに全停留所が Not にならず、要件と乖離します。
現在は「空集合=フィルタ適用なし」扱いのため、出発予定がゼロの時間帯でも bus 停留所が Not になりません。エラー時のフォールバックと「実際にゼロ件」の区別が必要です。
💡 例: エラーと空集合を区別して適用する案
- let active_bus_stops = if !bus_station_cds.is_empty() {
+ let active_bus_stops = if !bus_station_cds.is_empty() {
let (current_date, current_time) = get_current_jst();
match self
.station_repository
.get_active_bus_stop_station_cds(&bus_station_cds, ¤t_time, ¤t_date)
.await
{
- Ok(stops) => stops,
+ Ok(stops) => Some(stops),
Err(e) => {
tracing::warn!(
"Failed to get active bus stop station_cds: {}. Using empty set as fallback.",
e
);
- HashSet::new()
+ None
}
}
} else {
- HashSet::new()
+ None
};
- if !active_bus_stops.is_empty()
- && station.transport_type == TransportType::Bus
- && !active_bus_stops.contains(&station.station_cd)
- {
- station.stop_condition = crate::proto::StopCondition::Not;
- }
+ if let Some(active_bus_stops) = &active_bus_stops {
+ if station.transport_type == TransportType::Bus
+ && !active_bus_stops.contains(&station.station_cd)
+ {
+ station.stop_condition = crate::proto::StopCondition::Not;
+ }
+ }※ get_routes / get_routes_minimal / 近傍バス停反映も同様の扱いに揃える想定です。
Also applies to: 351-359, 392-405, 427-434, 710-736, 811-821, 853-880, 935-955
🤖 Prompt for AI Agents
In `@stationapi/src/use_case/interactor/query.rs` around lines 290 - 349, The code
currently treats an error and a genuine empty result identically for
active_bus_stops, causing "no filter" behavior when there are actually zero
departures; change active_bus_stops from a HashSet to an Option<HashSet<i32>> so
that on Ok(stops) you return Some(stops) (including Some(empty) for zero
results) and on Err(e) you return None (and log the error) — adjust consumers of
active_bus_stops accordingly to apply the filter when Option::Some is present
and skip filtering only when None; update the match around
station_repository.get_active_bus_stop_station_cds, the variable declaration for
active_bus_stops, and any uses in update_station_vec_with_attributes / related
get_routes/get_routes_minimal flows to follow this semantics.
SQLクエリを修正して、stations.line_cd → gtfs_routes → gtfs_trips の 関係を使い、特定の路線に属するバス停のみをフィルタリング対象に。 これにより、別路線が停車するバス停が誤ってアクティブと判定される 問題を解決。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@stationapi/src/infrastructure/station_repository.rs`:
- Around line 1573-1626: The time-window logic in
current_time_jst/total_minutes/start_minutes/end_minutes clamps across midnight
and misses previous/next-day GTFS trips and 24+:xx departure_time values; update
the logic to compute un-clamped start_minutes and end_minutes (allowing negative
and >=1440) and split query into up to two/three parts covering previous-day
(when start_minutes<0, map to 24:.. by adding 1440 and query with date =
prev_date), current-day (date = date), and next-day (when end_minutes>=1440, map
to 24:.. by subtracting 1440 and query with date = next_date), then UNION those
SELECTs (or run separate queries) to collect station_cd results and dedupe with
a HashSet; modify the SQL filters that compare gst.departure_time to accept
times like '24:30:00' (use string bounds matching the mapped 24+:xx values) and
adjust parameters ($1, $2, $3, $4) accordingly so
gtfs_calendar/gtfs_calendar_dates are consulted for the correct date per
subquery (refer to variables current_time_jst, start_minutes, end_minutes and
the query string).
| // Calculate time window (±30 minutes) | ||
| let time_parts: Vec<&str> = current_time_jst.split(':').collect(); | ||
| let hours: i32 = time_parts.first().unwrap_or(&"0").parse().unwrap_or(0); | ||
| let minutes: i32 = time_parts.get(1).unwrap_or(&"0").parse().unwrap_or(0); | ||
|
|
||
| // Calculate start and end times for the 30-minute window | ||
| let total_minutes = hours * 60 + minutes; | ||
| let start_minutes = (total_minutes - 30).max(0); | ||
| let end_minutes = total_minutes + 30; | ||
|
|
||
| let start_time = format!("{:02}:{:02}:00", start_minutes / 60, start_minutes % 60); | ||
| let end_time = format!("{:02}:{:02}:00", end_minutes / 60, end_minutes % 60); | ||
|
|
||
| // Query to find active bus stops: | ||
| // 1. Find service_ids that are active today based on gtfs_calendar and gtfs_calendar_dates | ||
| // 2. Find trips with those service_ids AND matching route (via line_cd) | ||
| // 3. Find stop_times within the time window | ||
| // 4. Map stop_ids to station_cds via stations.gtfs_stop_id | ||
| // (handles parent/child stop relationships) | ||
| let query = format!( | ||
| r#" | ||
| WITH active_services AS ( | ||
| -- Services that run on this day of week | ||
| SELECT gc.service_id | ||
| FROM gtfs_calendar gc | ||
| WHERE gc.{day_column} = true | ||
| AND gc.start_date <= $1 | ||
| AND gc.end_date >= $1 | ||
| -- Add exceptions (service added) | ||
| UNION | ||
| SELECT gcd.service_id | ||
| FROM gtfs_calendar_dates gcd | ||
| WHERE gcd.date = $1 | ||
| AND gcd.exception_type = 1 | ||
| -- Remove exceptions (service removed) | ||
| EXCEPT | ||
| SELECT gcd.service_id | ||
| FROM gtfs_calendar_dates gcd | ||
| WHERE gcd.date = $1 | ||
| AND gcd.exception_type = 2 | ||
| ) | ||
| SELECT DISTINCT s.station_cd | ||
| FROM stations s | ||
| JOIN gtfs_routes gr ON gr.line_cd = s.line_cd | ||
| JOIN gtfs_trips gt ON gt.route_id = gr.route_id | ||
| JOIN active_services ase ON ase.service_id = gt.service_id | ||
| JOIN gtfs_stop_times gst ON gst.trip_id = gt.trip_id | ||
| JOIN gtfs_stops gs ON gs.stop_id = gst.stop_id | ||
| WHERE s.station_cd = ANY($4) | ||
| AND s.gtfs_stop_id IS NOT NULL | ||
| AND (gs.stop_id = s.gtfs_stop_id OR gs.parent_station = s.gtfs_stop_id) | ||
| AND gst.departure_time >= $2 | ||
| AND gst.departure_time <= $3 | ||
| "#, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
find stationapi/src/infrastructure -name "*.rs" | head -20Repository: TrainLCD/StationAPI
Length of output: 358
🏁 Script executed:
wc -l stationapi/src/infrastructure/station_repository.rsRepository: TrainLCD/StationAPI
Length of output: 119
🏁 Script executed:
sed -n '1570,1630p' stationapi/src/infrastructure/station_repository.rsRepository: TrainLCD/StationAPI
Length of output: 2779
🏁 Script executed:
# Find GTFS schema/migration files
find . -type f \( -name "*.sql" -o -name "*.rs" \) | xargs grep -l "gtfs_stop_times" | head -10Repository: TrainLCD/StationAPI
Length of output: 218
🏁 Script executed:
# Look for schema definitions
find . -type f -name "*.sql" | xargs grep -l "departure_time" 2>/dev/null | head -5Repository: TrainLCD/StationAPI
Length of output: 86
🏁 Script executed:
cat ./data/create_table.sql | grep -A 50 "gtfs_stop_times"Repository: TrainLCD/StationAPI
Length of output: 4093
🏁 Script executed:
# Get more context on the function - find its full signature
sed -n '1500,1630p' stationapi/src/infrastructure/station_repository.rs | head -100Repository: TrainLCD/StationAPI
Length of output: 4273
🏁 Script executed:
# Search for function signature
rg "get_active_bus_stop_station_cds" -B 10 -A 2Repository: TrainLCD/StationAPI
Length of output: 18500
🏁 Script executed:
# Check if there's any date boundary logic elsewhere
rg "start_minutes|end_minutes" stationapi/Repository: TrainLCD/StationAPI
Length of output: 551
🏁 Script executed:
# Check tests for this function
rg "get_active_bus_stop_station_cds" stationapi/ -A 5 -B 5Repository: TrainLCD/StationAPI
Length of output: 16425
深夜帯(00:10、23:50など)で日跨ぎ±30分が欠落し、バス停が誤判定になります。
start_minutes = (total_minutes - 30).max(0) でクランプされるため、例えば00:10時点では window が [00:00, 00:40] となり、前日の 23:40-23:59 の便が落ちます。また、23:50 では window が [23:20, 24:20] となりますが、次の日のサービスはクエリされません。スキーマからも確認されるように、GTFS では departure_time が "25:30:00" のように 24:xx 表記を許容していることに対応していません。
前日/翌日のサービスも含めて検索する必要があります。例えば日跨ぎ時は、前日の 24:xx ウィンドウと翌日の 00:xx ウィンドウを UNION で統合し、結果を HashSet で統合する方法が考えられます。
🤖 Prompt for AI Agents
In `@stationapi/src/infrastructure/station_repository.rs` around lines 1573 -
1626, The time-window logic in
current_time_jst/total_minutes/start_minutes/end_minutes clamps across midnight
and misses previous/next-day GTFS trips and 24+:xx departure_time values; update
the logic to compute un-clamped start_minutes and end_minutes (allowing negative
and >=1440) and split query into up to two/three parts covering previous-day
(when start_minutes<0, map to 24:.. by adding 1440 and query with date =
prev_date), current-day (date = date), and next-day (when end_minutes>=1440, map
to 24:.. by subtracting 1440 and query with date = next_date), then UNION those
SELECTs (or run separate queries) to collect station_cd results and dedupe with
a HashSet; modify the SQL filters that compare gst.departure_time to accept
times like '24:30:00' (use string bounds matching the mapped 24+:xx values) and
adjust parameters ($1, $2, $3, $4) accordingly so
gtfs_calendar/gtfs_calendar_dates are consulted for the correct date per
subquery (refer to variables current_time_jst, start_minutes, end_minutes and
the query string).
|
やり直そう.. |
stop_condition=Notを返すように変更
サービス運行状況を考慮
Summary by CodeRabbit
新機能
テスト
✏️ Tip: You can customize this high-level summary in your review settings.