So the CTA finally brought the bus tracker to busses running through my neighborhood. It gives you a nice Google map showing you where busses currently are on the route, and a separate web interface telling you how long before a bus reaches a given spot. Nice, but I don't want to open a web browser for all of that. (PACE has actually had my busses for a while.)
Enter the bus command:
#!/usr/bin/env ruby
require "yaml"
require "cgi"
require "open-uri"
require "time"
Location=Struct.new(:name,:lines)
CTA=Struct.new(:line,:dir,:stop,:id) do
def url
"http://www.ctabustracker.com/bustime/wireless/html/eta.jsp?route=%s&direction=%s&stop=%s&id=%d" %
[self.line, CGI.escape(self.dir), CGI.escape(self.stop), self.id]
end
def times
html=open(self.url){|f| f.read}
mins=html.scan(%r{<b>(\d+).*MIN</b>}).flatten.map{|x| x.to_i}
times=mins.map{|x| Time.now+x*60}
mins.zip(times).map{|m,t| "#{t.hm} (#{m}m)"}.join(", ")
end
def description
"%s %s (%s): %s" % [self.line, self.stop, self.dir, self.times]
end
end
PACE=Struct.new(:line,:dir,:stop,:name) do
def url
"http://gis.pacebus.com/webwatch/ada.aspx?r=%d&d=%d&s=%d" %
[self.line, self.dir, self.stop]
end
def times
html=open(self.url){|f| f.read}
times=html.scan(%r{>(\d+:\d+ [AP]\.M\.)}).flatten.map{|x| Time.parse(x)}
mins=times.map{|x| ((x-Time.now)/60).to_i }
mins.zip(times).map{|m,t| "#{t.hm} (#{m}m)"}.join(", ")
end
def description
"#{self.name}: #{self.times}"
end
end
class Time
def hm
strftime "%H:%M"
end
end
locations=YAML.load_file("#{ENV['HOME']}/.bus.yaml")
locations.each do |location|
puts location.name
location.lines.each do |line|
puts " #{line.description}"
end
end
And my ~/.bus.yaml
---
- !ruby/struct:Location
name: Home
lines:
- !ruby/struct:CTA
line: 96
dir: East Bound
stop: Lunt & California
id: 12043
- !ruby/struct:CTA
line: 96
dir: West Bound
stop: Lunt & California
id: 12077
- !ruby/struct:CTA
line: 93
dir: North Bound
stop: California & Lunt
id: 11915
- !ruby/struct:CTA
line: 93
dir: South Bound
stop: California & Lunt
id: 11871
- !ruby/struct:CTA
line: 49B
dir: South Bound
stop: Western & Lunt
id: 1698
- !ruby/struct:PACE
line: 290
dir: 1
stop: 22090
name: 290 Touhy & California (East Bound)
The secret codes (id for the CTA, and stop and dir for PACE) need to be
filled in by visitng the bus you're interested in on the bus tracker first. For
PACE, name is the name of the line --- since most of the site's inner workings
are through secret codes, you need to provide a human-readable name yourself.
Now I can just run the bus command and see all of the nearby busses at a glance:
Home
96 Lunt & California (East Bound): 14:46 (16m)
96 Lunt & California (West Bound): 14:36 (6m), 14:54 (24m)
93 California & Lunt (North Bound): 14:39 (9m), 14:51 (21m)
93 California & Lunt (South Bound): 14:33 (3m), 14:55 (25m)
49B Western & Lunt (South Bound): 14:37 (7m), 14:48 (18m), 14:58 (28m)
290 Touhy & California (East Bound): 14:33 (2m), 14:44 (13m), 14:50 (19m)
Whoops. Here comes by #93 now. Better get going.