jbinto / nextbus-ttc

Ruby gem for NextBus TTC vehicle predictions
MIT License
0 stars 0 forks source link

Predictions broken: assumes one direction per prediction #2

Open jbinto opened 9 years ago

jbinto commented 9 years ago

Summary: Predictions currently don't work:

predictions = Nextbus::Prediction.all('ttc', '504', '10272')
NoMethodError: undefined method `prediction' for #<Array:0x007f9973403d00>
from /Users/jbinto/.gem/ruby/2.1.5/bundler/gems/nextbus-ttc-75bf0addd2aa/lib/nextbus/client.rb:33:in `predictions'

Details:

It seems that there is a strong assumption in the original nextbus code that the following is sufficient for a prediction:

(agency, route, stop)

Namely, this implies that we don't need a direction_tag to get a prediction.

The original fixture from the nextbus gem for Boston:

<?xml version="1.0" encoding="UTF-8"?>
<body copyright="All data copyright MBTA 2010.">
<predictions agencyTitle="MBTA" routeTitle="39" routeTag="39" stopTitle="105 S Huntington (Stop 22365)">
  <direction title="Outbound">
    <prediction seconds="745" minutes="12" epochTime="1266681828070" isDeparture="false" dirTag="out" vehicle="1041" block="S393_6"/>
    <prediction seconds="1299" minutes="21" epochTime="1266681828075" isDeparture="false" dirTag="out" vehicle="1022" block="S393_7"/>
    <prediction seconds="1929" minutes="32" epochTime="1266683011947" isDeparture="false" dirTag="out" vehicle="1027" block="S393_1"/>
    <prediction seconds="2529" minutes="42" epochTime="1266683611947" isDeparture="false" dirTag="out" vehicle="1040" block="S393_2"/>
    <prediction seconds="3129" minutes="52" epochTime="1266684211947" isDeparture="false" dirTag="out" vehicle="1037" block="S393_8"/>
  </direction>
</predictions>
</body>

And the current TTC fixture:

<?xml version="1.0" encoding="utf-8" ?> 
<body copyright="All data copyright Toronto Transit Commission 2014.">
<predictions agencyTitle="Toronto Transit Commission" routeTitle="504-King" routeTag="504" stopTitle="Queen St East At River St" stopTag="10272">
  <direction title="West - 504 King Replacement Bus towards Roncesvalles and Queen">
  <prediction epochTime="1418168810253" seconds="187" minutes="3" isDeparture="false" branch="504" dirTag="504_1_504BUS" vehicle="7704" block="504_83_582" tripTag="25116052" />
  </direction>
  <direction title="West - 504 King Replacement Bus towards Dundas West Station via King">
  <prediction epochTime="1418170640345" seconds="2017" minutes="33" isDeparture="false" affectedByLayover="true" branch="504" dirTag="504_1_504BUSdw" vehicle="1654" block="504_76_512" tripTag="25116043" />
  </direction>
  <direction title="West - 504 King towards Dundas West Station via King">
  <prediction epochTime="1418168727393" seconds="104" minutes="1" isDeparture="false" branch="504" dirTag="504_1_504" vehicle="4183" block="504_22_220" tripTag="25115971" />
  <prediction epochTime="1418169094161" seconds="470" minutes="7" isDeparture="false" branch="504" dirTag="504_1_504" vehicle="4101" block="504_18_180" tripTag="25115965" />
  <prediction epochTime="1418169269296" seconds="646" minutes="10" isDeparture="false" branch="504" dirTag="504_1_504" vehicle="4012" block="504_26_260" tripTag="25115975" />
  <prediction epochTime="1418169376746" seconds="753" minutes="12" isDeparture="false" affectedByLayover="true" branch="504" dirTag="504_1_504" vehicle="4038" block="504_30_300" tripTag="25115980" />
  <prediction epochTime="1418169789699" seconds="1166" minutes="19" isDeparture="false" affectedByLayover="true" branch="504" dirTag="504_1_504" vehicle="4220" block="504_31_22" tripTag="25115982" />
  </direction>
</predictions>
</body>

The main difference being that nextbus assumes there will only ever be one <direction> tag inside of <predictions>.

This might take a little bit more work than #1.

"Easiest Thing That Could Possibly Work™": Change the signature of predictions to require not only a route_id, but a direction_tag as well. Then we could filter for the specific direction_tag. (ed: I have a wicked sense of déjà vu, I feel like I've done this before.)

Other considerations:

jbinto commented 9 years ago

This is getting more complicated.

Consider Nextbus::Client.predictions:

def predictions(agency_id, route_id, stop_id)
      response = self.class.do_request("predictions", {"a" => agency_id, "r" => route_id, "s" => stop_id})
      response.predictions.direction.prediction
    end

When there's 2 or more directions:

> response.predictions.direction.length
=> 2
> response.predictions.direction.class
=> Array
> response.predictions.direction.first.prediction.length
=> 2
> response.predictions.direction.first.prediction.first.epoch_time
=> "1418172993027"

When there's only one direction:

> response.predictions.direction.length
=> 2
> response.predictions.direction.class
=> Hashie::Mash
> response.predictions.direction.first.prediction.length
NoMethodError: undefined method `prediction' for ["title", "West - 504 King towards Dundas West Station via King"]:Array
from (pry):6:in `predictions'
> response.predictions.direction.prediction.length
=> 5
> response.predictions.direction.prediction.first.epoch_time
=> "1418171691675"

In other words:

response.predictions.direction could be a Hashie::Mash, or an Array of Hashie::Mash.

Shouldn't be the biggest deal ever, but it is a bit annoying.