Skip to content

Commit

Permalink
Feat: Mta Subway translator & and realtime ext 'stop_name' field (#4)
Browse files Browse the repository at this point in the history
* initial translator & tests for mta subway

* parses date to GMT, adjustments to stop id, removes track

* removes DS_store

* added mtasubway to the registry

* updates tests, handles multiple stops

* added stop name to realtime extension

* remove print statement and unused import
  • Loading branch information
AlexChaseJones authored and Tyler Green committed Oct 2, 2019
1 parent 4af762d commit 5b97a1f
Show file tree
Hide file tree
Showing 8 changed files with 363 additions and 11 deletions.
1 change: 1 addition & 0 deletions gtfs_realtime_translators/bindings/intersection.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ message IntersectionStopTimeUpdate {
optional string track = 1;
optional transit_realtime.TripUpdate.StopTimeEvent scheduled_arrival = 2;
optional transit_realtime.TripUpdate.StopTimeEvent scheduled_departure = 3;
optional string stop_name = 4;
}

extend transit_realtime.TripUpdate {
Expand Down
28 changes: 18 additions & 10 deletions gtfs_realtime_translators/bindings/intersection_pb2.py

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

3 changes: 3 additions & 0 deletions gtfs_realtime_translators/factories/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def create(*args, **kwargs):
track = kwargs.get('track', None)
scheduled_arrival = kwargs.get('scheduled_arrival_time', None)
scheduled_departure = kwargs.get('scheduled_departure_time', None)
stop_name = kwargs.get('stop_name', None)

trip_descriptor = gtfs_realtime.TripDescriptor(trip_id=trip_id,
route_id=route_id)
Expand All @@ -49,6 +50,8 @@ def create(*args, **kwargs):
stop_time_update.Extensions[intersection_gtfs_realtime.intersection_stop_time_update].scheduled_arrival.time = scheduled_arrival
if scheduled_departure:
stop_time_update.Extensions[intersection_gtfs_realtime.intersection_stop_time_update].scheduled_departure.time = scheduled_departure
if stop_name:
stop_time_update.Extensions[intersection_gtfs_realtime.intersection_stop_time_update].stop_name = stop_name

trip_update = gtfs_realtime.TripUpdate(trip=trip_descriptor,
stop_time_update=[stop_time_update])
Expand Down
3 changes: 2 additions & 1 deletion gtfs_realtime_translators/registry/registry.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import warnings

from gtfs_realtime_translators.translators import LaMetroGtfsRealtimeTranslator, \
SeptaRegionalRailTranslator
SeptaRegionalRailTranslator, MtaSubwayGtfsRealtimeTranslator

class TranslatorKeyWarning(Warning):
pass
Expand All @@ -10,6 +10,7 @@ class TranslatorRegistry:
TRANSLATORS = {
'la-metro': LaMetroGtfsRealtimeTranslator,
'septa-regional-rail': SeptaRegionalRailTranslator,
'mta-subway': MtaSubwayGtfsRealtimeTranslator
}

@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
@@ -1,2 +1,3 @@
from .la_metro import LaMetroGtfsRealtimeTranslator
from .septa_regional_rail import SeptaRegionalRailTranslator
from .mta_subway import MtaSubwayGtfsRealtimeTranslator
59 changes: 59 additions & 0 deletions gtfs_realtime_translators/translators/mta_subway.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import pendulum

from gtfs_realtime_translators.factories import TripUpdate, FeedMessage


class MtaSubwayGtfsRealtimeTranslator:
def __init__(self, data):
entities = []
for stop in data:
for group in stop["groups"]:
for idx, arrival in enumerate(group["times"]):
route_id = group['route']['id']
stop_name = stop['stop']['name']
entities.append(self.__make_trip_update(idx, route_id, stop_name, arrival))

self.feed_message = FeedMessage.create(entities=entities)

@classmethod
def get_stop_id(cls, stop_id):
"""
Stop IDs from MTA Subway come in the form MTASBY:<stop id>.
We must parse the stop_id only.
"""
try:
return stop_id.split(':')[1]
except Exception:
return stop_id


@classmethod
def to_gmt_timestamp(cls, timestamp):
return int(pendulum.from_timestamp(timestamp).subtract(hours=4).timestamp())

@classmethod
def __make_trip_update(cls, _id, route_id, stop_name, arrival):
entity_id = str(_id + 1)
arrival_time = cls.to_gmt_timestamp(arrival['serviceDay'] + arrival['realtimeArrival'])
departure_time = cls.to_gmt_timestamp(arrival['serviceDay'] + arrival['realtimeDeparture'])
trip_id = arrival['tripId']
stop_id = cls.get_stop_id(arrival['stopId'])

##### Intersection Extensions
headsign = arrival['tripHeadsign']
scheduled_arrival_time = cls.to_gmt_timestamp(arrival['serviceDay'] + arrival['scheduledArrival'])
scheduled_departure_time = cls.to_gmt_timestamp(arrival['serviceDay'] + arrival['scheduledDeparture'])
return TripUpdate.create(entity_id=entity_id,
arrival_time=arrival_time,
departure_time=departure_time,
trip_id=trip_id,
route_id=route_id,
stop_id=stop_id,
stop_name=stop_name,
headsign=headsign,
scheduled_arrival_time=scheduled_arrival_time,
scheduled_departure_time=scheduled_departure_time)


def serialize(self):
return self.feed_message.SerializeToString()
Loading

0 comments on commit 5b97a1f

Please sign in to comment.