Skip to content

Instantly share code, notes, and snippets.

@mwerner
Last active November 17, 2016 00:56
Show Gist options
  • Save mwerner/124304f4b89b9fcd08a53b3fbb7e0028 to your computer and use it in GitHub Desktop.
Save mwerner/124304f4b89b9fcd08a53b3fbb7e0028 to your computer and use it in GitHub Desktop.
Bart Realtime CLI
#!/usr/bin/env ruby
# $ bart
# Usage:
# bart stations #=> list all stations with abbreviations
# bart ORIG[:DEST[:DEST]] #=> show estimates for up to three origin stations
# Example:
# $ bart POWL:PITT:RICH:PHIL RICH:MLBR
# POWL=>PITT Pittsburg/Bay Point 10 min, 25 min, 40 min
# POWL=>PHIL Pleasant Hill 34 min, 64 min
# POWL=>RICH Richmond 3 min, 18 min, 32 min
# RICH=>MLBR Millbrae 13 min, 28 min
require 'open-uri'
require 'nokogiri'
class Bart
KEY = 'MW9S-E7SL-26DU-VV8V'
def self.help
[
"Usage:",
" bart stations #=> list all stations with abbreviations",
" bart ORIG[:DEST[:DEST]] #=> show estimates for up to three origin stations",
"", "Example:",
" $ bart POWL:PITT:RICH:PHIL RICH:MLBR",
" POWL=>PITT Pittsburg/Bay Point 10 min, 25 min, 40 min",
" POWL=>PHIL Pleasant Hill 34 min, 64 min",
" POWL=>RICH Richmond 3 min, 18 min, 32 min",
" RICH=>MLBR Millbrae 13 min, 28 min"
]
end
def self.stations
doc = Nokogiri::XML open(stn_url)
doc.css('station').map do |station|
{ abbr: station.css('abbr').text, name: station.css('name').text }
end
end
def self.times(station)
doc = Nokogiri::XML open(etd_url(station))
{
name: doc.css('station name').text,
abbr: doc.css('station abbr').text,
times: extract_times(doc)
}
end
private
def self.extract_times(doc)
doc.css('station etd').map do |etd|
{
destination: etd.css('destination').text,
abbreviation: etd.css('abbreviation').text,
arrivals: humanize(etd.css('estimate').map { |e| e.css('minutes').text.to_i })
}
end
end
def self.humanize(times)
times.map do |time|
time == 0 ? 'now' : "#{time} min"
end.join(', ')
end
def self.stn_url
"http://api.bart.gov/api/stn.aspx?cmd=stns&key=#{KEY}"
end
def self.etd_url(station)
"http://api.bart.gov/api/etd.aspx?cmd=etd&orig=#{station}&key=#{KEY}"
end
end
origin, *destinations = ARGV[0].to_s.split(':')
if origin.nil?
puts Bart.help
exit(0)
elsif origin == 'stations'
Bart.stations.each{ |s| printf "%-4s %s\n", s[:abbr], s[:name] }
exit 0
end
2.times do |n|
Bart.times(origin)[:times].each do |time|
next unless destinations.empty? || destinations.include?(time[:abbreviation])
printf "%-30s %s\n", "#{origin}=>#{time[:destination]}", time[:arrivals]
end
origin, *destinations = ARGV[n+1].to_s.split(':')
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment