Skip to content

Commit

Permalink
TRAN-7600: Add translator for MNMT (#60)
Browse files Browse the repository at this point in the history
* TRAN-7600: add translator for mnmt

* TRAN-7600: update registry

* TRAN-7600: cast stop_id

* TRAN-7600: set arrival times

* TRAN-7600: stop name

* TRAN-7600: remove seconds from time parser

* TRAN-7600: flip condition

* TRAN-7600: timezone

* TRAN-7600: create trip_update with timezone

* TRAN-7600: use actual field

* TRAN-7600: add arrival time

* TRAN-7600: append terminal to route short name

* TRAN-7600: add tests

* TRAN-7600: newline
  • Loading branch information
joshverma authored Dec 19, 2023
1 parent ecece56 commit f1163e0
Show file tree
Hide file tree
Showing 5 changed files with 230 additions and 1 deletion.
3 changes: 2 additions & 1 deletion gtfs_realtime_translators/registry/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
SeptaRegionalRailTranslator, MtaSubwayGtfsRealtimeTranslator, NjtRailGtfsRealtimeTranslator, \
CtaSubwayGtfsRealtimeTranslator, CtaBusGtfsRealtimeTranslator, PathGtfsRealtimeTranslator, \
PathNewGtfsRealtimeTranslator, SwiftlyGtfsRealtimeTranslator, WcdotGtfsRealTimeTranslator, \
NjtBusGtfsRealtimeTranslator, MbtaGtfsRealtimeTranslator
NjtBusGtfsRealtimeTranslator, MbtaGtfsRealtimeTranslator, MnmtGtfsRealtimeTranslator


class TranslatorKeyWarning(Warning):
Expand All @@ -25,6 +25,7 @@ class TranslatorRegistry:
'swiftly': SwiftlyGtfsRealtimeTranslator,
'wcdot-bus': WcdotGtfsRealTimeTranslator,
'mbta': MbtaGtfsRealtimeTranslator,
'mnmt': MnmtGtfsRealtimeTranslator
}

@classmethod
Expand Down
1 change: 1 addition & 0 deletions gtfs_realtime_translators/translators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
from .swiftly import SwiftlyGtfsRealtimeTranslator
from .wcdot_bus import WcdotGtfsRealTimeTranslator
from .mbta import MbtaGtfsRealtimeTranslator
from .mnmt import MnmtGtfsRealtimeTranslator
81 changes: 81 additions & 0 deletions gtfs_realtime_translators/translators/mnmt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import json

import pendulum

from gtfs_realtime_translators.factories import TripUpdate, FeedMessage


class MnmtGtfsRealtimeTranslator:
TIMEZONE = 'America/Chicago'

def __call__(self, data):
json_data = json.loads(data)

stops_list = json_data.get('stops')
departures_list = json_data.get('departures')

entities = []
if stops_list and departures_list:
entities = self.__make_trip_updates(stops_list, departures_list)

return FeedMessage.create(entities=entities)

@classmethod
def __make_trip_updates(cls, stops_list, departures_list):
trip_updates = []
stop_name = stops_list[0].get("description")

for index, departure in enumerate(departures_list):
entity_id = str(index + 1)

trip_id = departure.get('trip_id')

stop_id = departure.get('stop_id')
if stop_id:
stop_id = str(stop_id)

headsign = departure.get('description')
route_id = departure.get('route_id')
direction_id = departure.get('direction_id')

departure_time, scheduled_departure_time = None, None
arrival_time, scheduled_arrival_time = None, None
if cls.__is_realtime_departure(departure):
departure_time = departure.get('departure_time')
arrival_time = departure_time
else:
scheduled_departure_time = departure.get('departure_time')
scheduled_arrival_time = scheduled_departure_time

route_short_name = cls.__get_route_short_name(departure)

trip_update = TripUpdate.create(entity_id=entity_id,
departure_time=departure_time,
arrival_time=arrival_time,
scheduled_departure_time=scheduled_departure_time,
scheduled_arrival_time=scheduled_arrival_time,
trip_id=trip_id,
route_id=route_id,
route_short_name=route_short_name,
stop_id=stop_id,
stop_name=stop_name,
headsign=headsign,
direction_id=direction_id,
agency_timezone=cls.TIMEZONE
)

trip_updates.append(trip_update)

return trip_updates

@classmethod
def __is_realtime_departure(cls, departure):
return departure.get('actual') is True

@classmethod
def __get_route_short_name(cls, departure):
terminal = departure.get('terminal')
route_short_name = departure.get('route_short_name')
if terminal:
return f'{route_short_name}{terminal}'
return route_short_name
45 changes: 45 additions & 0 deletions test/fixtures/mnmt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"stops": [
{
"stop_id": 11191,
"latitude": 45.013401,
"longitude": -93.287947,
"description": "Lyndale Ave N & Lowry Ave N"
}
],
"alerts": [
{
"stop_closed": false,
"alert_text": "The following stop is closed for Routes 3, 7 and 22 until further notice: Washington Ave S & Park Ave - Stop #19306 (westbound)"
}
],
"departures": [
{
"actual": true,
"trip_id": "24557038-DEC23-MVS-BUS-Weekday-03",
"stop_id": 11191,
"departure_text": "14 Min",
"departure_time": 1702923655,
"description": "Brklyn Ctr Tc / N Lyndale / Via Penn Av",
"route_id": "22",
"route_short_name": "22",
"direction_id": 0,
"direction_text": "NB",
"terminal": "A",
"schedule_relationship": "Scheduled"
},
{
"actual": false,
"trip_id": "24557032-DEC23-MVS-BUS-Weekday-03",
"stop_id": 11191,
"departure_text": "12:42",
"departure_time": 1702924920,
"description": "Brklyn Ctr Tc / N Lyndale / Via Humboldt",
"route_id": "22",
"route_short_name": "22",
"direction_id": 0,
"direction_text": "NB",
"schedule_relationship": "Scheduled"
}
]
}
101 changes: 101 additions & 0 deletions test/test_mnmt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import pytest

from gtfs_realtime_translators.translators import MnmtGtfsRealtimeTranslator
from gtfs_realtime_translators.bindings import intersection_pb2 as intersection_gtfs_realtime
from gtfs_realtime_translators.factories import FeedMessage


@pytest.fixture
def mnmt():
with open('test/fixtures/mnmt.json') as f:
raw = f.read()
return raw


def test_mnmt_realtime_departure(mnmt):
translator = MnmtGtfsRealtimeTranslator()
message = translator(mnmt)

entity = message.entity[0]
trip_update = entity.trip_update
stop_time_update = trip_update.stop_time_update[0]

assert message.header.gtfs_realtime_version == FeedMessage.VERSION
assert entity.id == '1'

assert stop_time_update.departure.time == 1702923655
assert stop_time_update.arrival.time == 1702923655

assert not stop_time_update.Extensions[
intersection_gtfs_realtime.intersection_stop_time_update].\
scheduled_arrival.time
assert not stop_time_update.Extensions[
intersection_gtfs_realtime.intersection_stop_time_update].\
scheduled_departure.time


def test_mnmt_scheduled_departure(mnmt):
translator = MnmtGtfsRealtimeTranslator()
message = translator(mnmt)

entity = message.entity[1]
trip_update = entity.trip_update
stop_time_update = trip_update.stop_time_update[0]

assert message.header.gtfs_realtime_version == FeedMessage.VERSION
assert entity.id == '2'

assert not stop_time_update.departure.time
assert not stop_time_update.arrival.time

assert stop_time_update.Extensions[
intersection_gtfs_realtime.intersection_stop_time_update].\
scheduled_arrival.time == 1702924920
assert stop_time_update.Extensions[
intersection_gtfs_realtime.intersection_stop_time_update].\
scheduled_departure.time == 1702924920


def test_mnmt_route_short_name_with_terminal(mnmt):
translator = MnmtGtfsRealtimeTranslator()
message = translator(mnmt)

entity = message.entity[0]
trip_update = entity.trip_update

assert message.header.gtfs_realtime_version == FeedMessage.VERSION
assert entity.id == '1'

assert trip_update.Extensions[
intersection_gtfs_realtime.intersection_trip_update].\
route_short_name == '22A'


def test_mnmt_route_short_name_without_terminal(mnmt):
translator = MnmtGtfsRealtimeTranslator()
message = translator(mnmt)

entity = message.entity[1]
trip_update = entity.trip_update

assert message.header.gtfs_realtime_version == FeedMessage.VERSION
assert entity.id == '2'

assert trip_update.Extensions[
intersection_gtfs_realtime.intersection_trip_update].\
route_short_name == '22'


def test_mnmt_headsign(mnmt):
translator = MnmtGtfsRealtimeTranslator()
message = translator(mnmt)

entity = message.entity[0]
trip_update = entity.trip_update

assert message.header.gtfs_realtime_version == FeedMessage.VERSION
assert entity.id == '1'

assert trip_update.Extensions[
intersection_gtfs_realtime.intersection_trip_update].headsign \
== 'Brklyn Ctr Tc / N Lyndale / Via Penn Av'

0 comments on commit f1163e0

Please sign in to comment.