Skip to content
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
93e0333
fix:format vehicleId as combined agency and vehicle ID
3rabiii May 17, 2026
5c11786
fix: use 0-based stop ordinals for arrival routing and sequence matching
3rabiii May 17, 2026
03198e1
fix: implement route short name and trip headsign fallbacks
3rabiii May 17, 2026
e30e386
fix: ensure lastUpdateTime serializes to 0 when empty
3rabiii May 17, 2026
e18276c
fix: accurately format response for cancelled trips
3rabiii May 17, 2026
c192427
fix: derive entry status from tripStatus
3rabiii May 17, 2026
b9228ce
zero out predicted times when not predicted
3rabiii May 18, 2026
6b06769
fix: zero out lastUpdateTime for cancelled trips
3rabiii May 20, 2026
b5e0554
fix: use ordinal index instead of raw stop_sequence for block calcula…
3rabiii May 20, 2026
a9feb3a
fix: support YYYY-MM-DD format for serviceDate parameter
3rabiii May 20, 2026
82366f1
fix: support yyyy-MM-dd_HH-mm-ss formate for time parameter
3rabiii May 20, 2026
c369613
fix: support includeReferences=false query parameter
3rabiii May 20, 2026
c7ef9e1
feat: implement expand-outward search for stopSequence
3rabiii May 21, 2026
9842120
fix: resolve loop route ambiguity by selecting closest stop visit
3rabiii May 21, 2026
fa78c56
chore: update openapi spec from upstream
3rabiii May 21, 2026
4d831dd
fix: resolve blockTripSequence calculation
3rabiii May 22, 2026
faa1edd
feat: add block sequence resolver and distance-based stop lookup
3rabiii May 23, 2026
3a985aa
fix: correct numberOfStopsAway calculation using tripStatus.NextStop
3rabiii May 23, 2026
881daf0
test: update numberOfStopsAway assertions to align with Java parity
3rabiii May 23, 2026
5095e83
refactor: remove obsolete stop-finding functions and dead code
3rabiii May 23, 2026
446d15b
style: fix linter warning
3rabiii May 23, 2026
3f4dc8a
Merge main into branch and resolve openapi conflict
3rabiii May 23, 2026
de044be
fix: handle missing sequence lookups with -1 sentinel value
3rabiii May 23, 2026
db7a066
refactor: introduce shapeContext to reduce findStopsByDistance parame…
3rabiii May 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gtfsdb/block_layover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func TestBuildBlockLayoverIndex_PopulatesTable(t *testing.T) {
SELECT block_id, route_id, service_id, layover_stop_id, next_trip_id
FROM block_layover`)
require.NoError(t, err)
defer rows.Close()
defer func() { _ = rows.Close() }()

checked := 0
for rows.Next() {
Expand Down
17 changes: 12 additions & 5 deletions gtfsdb/query.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1229,7 +1229,8 @@ FROM (
-- Optimized queries using SQLite window functions

-- name: GetTargetStopTimeWithTotalStops :one
-- Fetches a specific stop time for a trip+stop, along with the total stop count,
-- Fetches a specific stop time for a trip+stop, along with the total stop count
-- and a 0-based trip-relative ordinal (stop_ordinal) that is safe for sparse GTFS stop_sequences.
SELECT
st.trip_id,
st.arrival_time,
Expand All @@ -1241,14 +1242,17 @@ SELECT
st.drop_off_type,
st.shape_dist_traveled,
st.timepoint,
(SELECT COUNT(*) FROM stop_times st3 WHERE st3.trip_id = @trip_id AND st3.stop_sequence < st.stop_sequence) AS stop_ordinal,
(SELECT COUNT(*) FROM stop_times st2 WHERE st2.trip_id = @trip_id) AS total_stops
FROM stop_times st
WHERE st.trip_id = @trip_id AND st.stop_id = @stop_id
ORDER BY st.stop_sequence
WHERE st.trip_id = @trip_id AND st.stop_id = @stop_id AND CAST(@current_time AS INTEGER) IS NOT NULL
ORDER BY ABS(st.arrival_time - CAST(?3 AS INTEGER)), st.stop_sequence
LIMIT 1;

-- name: GetTargetStopTimeWithTotalStopsBySequence :one
-- Fetches a specific stop time for a trip+stop+sequence, along with the total stop count,
-- Fetches a specific stop time for a trip+stop+ordinal, along with the total stop count.
-- Uses a 0-based trip-relative ordinal (stop_ordinal) for matching instead of raw GTFS stop_sequence.
-- The ordinal equals the count of stops whose stop_sequence is strictly less than this row's.
SELECT
st.trip_id,
st.arrival_time,
Expand All @@ -1260,9 +1264,12 @@ SELECT
st.drop_off_type,
st.shape_dist_traveled,
st.timepoint,
(SELECT COUNT(*) FROM stop_times st3 WHERE st3.trip_id = @trip_id AND st3.stop_sequence < st.stop_sequence) AS stop_ordinal,
(SELECT COUNT(*) FROM stop_times st2 WHERE st2.trip_id = @trip_id) AS total_stops
FROM stop_times st
WHERE st.trip_id = @trip_id AND st.stop_id = @stop_id AND st.stop_sequence = @stop_sequence
WHERE st.trip_id = @trip_id
AND st.stop_id = @stop_id
AND (SELECT COUNT(*) FROM stop_times st4 WHERE st4.trip_id = @trip_id AND st4.stop_sequence < st.stop_sequence) = CAST(@stop_sequence AS INTEGER)
LIMIT 1;

-- name: GetBlockTripSequence :one
Expand Down
28 changes: 20 additions & 8 deletions gtfsdb/query.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions gtfsdb/stops_rtree.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (q *Queries) GetActiveStopsWithinBounds(ctx context.Context, arg GetActiveS
if err != nil {
return nil, err
}
defer rows.Close()
defer func() { _ = rows.Close() }()

var items []Stop
for rows.Next() {
Expand Down Expand Up @@ -95,7 +95,7 @@ func (q *Queries) GetStopIDsWithinBounds(ctx context.Context, arg GetStopIDsWith
if err != nil {
return nil, err
}
defer rows.Close()
defer func() { _ = rows.Close() }()

var ids []string
for rows.Next() {
Expand Down Expand Up @@ -178,7 +178,7 @@ func (q *Queries) GetActiveRoutesWithinBounds(ctx context.Context, arg GetActive
if err != nil {
return nil, err
}
defer rows.Close()
defer func() { _ = rows.Close() }()
var items []Route
for rows.Next() {
var i Route
Expand Down
2 changes: 1 addition & 1 deletion internal/models/arrival_and_departure.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type ArrivalAndDeparture struct {
DistanceFromStop float64 `json:"distanceFromStop"`
Frequency *Frequency `json:"frequency"`
HistoricalOccupancy string `json:"historicalOccupancy"`
LastUpdateTime ModelTime `json:"lastUpdateTime,omitzero"`
LastUpdateTime ModelTime `json:"lastUpdateTime"`
NumberOfStopsAway int `json:"numberOfStopsAway"`
OccupancyStatus string `json:"occupancyStatus"`
Predicted bool `json:"predicted"`
Expand Down
4 changes: 2 additions & 2 deletions internal/models/current_time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestCurrentTimeModel(t *testing.T) {
timeModel.ReadableTime, unmarshaledModel.ReadableTime)
}

if !unmarshaledModel.Time.Time.Equal(timeModel.Time.Time) {
if !unmarshaledModel.Time.Equal(timeModel.Time.Time) {
t.Errorf("Expected Time %v, got %v",
timeModel.Time, unmarshaledModel.Time)
}
Expand Down Expand Up @@ -74,7 +74,7 @@ func TestCurrentTimeData(t *testing.T) {
timeData.Entry.ReadableTime, unmarshaledData.Entry.ReadableTime)
}

if !unmarshaledData.Entry.Time.Time.Equal(timeData.Entry.Time.Time) {
if !unmarshaledData.Entry.Time.Equal(timeData.Entry.Time.Time) {
t.Errorf("Expected Entry.Time %v, got %v",
timeData.Entry.Time, unmarshaledData.Entry.Time)
}
Expand Down
1 change: 1 addition & 0 deletions internal/models/trip_details.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func (ts *TripStatus) SetPredicted(predicted bool) {
// SituationIDs and VehicleFeatures default to empty slices (never null in JSON).
func NewTripStatus() *TripStatus {
status := &TripStatus{
BlockTripSequence: -1,
OccupancyCapacity: -1,
OccupancyCount: -1,
SituationIDs: []string{},
Expand Down
2 changes: 1 addition & 1 deletion internal/models/trip_details_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func TestNewEmptyTripDetails(t *testing.T) {
tripDetails := NewEmptyTripDetails()

assert.Equal(t, "", tripDetails.TripID)
assert.True(t, tripDetails.ServiceDate.Time.IsZero())
assert.True(t, tripDetails.ServiceDate.IsZero())
assert.Nil(t, tripDetails.Frequency)
assert.Nil(t, tripDetails.Status)
assert.Nil(t, tripDetails.Schedule)
Expand Down
Loading
Loading