muni 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +1 -0
- data/Rakefile +1 -0
- data/bin/muni +67 -0
- data/lib/muni.rb +7 -0
- data/lib/muni/base.rb +27 -0
- data/lib/muni/direction.rb +12 -0
- data/lib/muni/prediction.rb +20 -0
- data/lib/muni/route.rb +73 -0
- data/lib/muni/stop.rb +13 -0
- data/lib/muni/version.rb +3 -0
- data/muni.gemspec +28 -0
- data/spec/route_spec.rb +12 -0
- data/spec/stop_spec.rb +14 -0
- metadata +132 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Hello
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/bin/muni
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby -*-
|
3
|
+
|
4
|
+
require 'muni'
|
5
|
+
require 'thor'
|
6
|
+
|
7
|
+
class MUNI < Thor
|
8
|
+
desc "list", "Lists all routes"
|
9
|
+
def list
|
10
|
+
begin
|
11
|
+
Muni::Route.find(:all).each do |route|
|
12
|
+
say_status route.tag, route.title, :green
|
13
|
+
end
|
14
|
+
rescue Muni::NextBusError => e
|
15
|
+
say_status "ERROR", e.message, :red
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "show [ROUTE_TAG] [DIRECTION]", "Shows a specifc route by name"
|
20
|
+
method_options %w( verbose -v ) => :boolean
|
21
|
+
def show(tag, direction = nil)
|
22
|
+
begin
|
23
|
+
route = Muni::Route.find(tag)
|
24
|
+
say_status route.tag, route.title, :green
|
25
|
+
dirs = direction ? [route.send(direction.downcase.to_sym)] : route.directions
|
26
|
+
dirs.each do |direction|
|
27
|
+
say_status direction.id, direction.name, :yellow
|
28
|
+
if options.verbose
|
29
|
+
print_table direction.stops.collect{|stop| [stop.tag, stop.title]}, {:ident => 8}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
rescue Muni::NextBusError => e
|
33
|
+
say_status "ERROR", e.message, :red
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "predict [ROUTE] [DIRECTION] [STOP]", "Retrieve predictions for a route at a specific stop"
|
38
|
+
def predict(route, direction, *stop)
|
39
|
+
# Join the remaining arguments so that predict can be called without
|
40
|
+
# having to quote the stop name.
|
41
|
+
stop = stop.join(' ')
|
42
|
+
|
43
|
+
# Get the bus route information
|
44
|
+
# TODO Only do this if necessary
|
45
|
+
bus = Muni::Route.find(route)
|
46
|
+
|
47
|
+
# Look up the stop information unless a numerica stop tag is specified
|
48
|
+
stop = bus.send(direction.downcase.to_sym).stop_at(stop).tag unless stop =~ /[1-9][0-9]+/
|
49
|
+
|
50
|
+
# Look up the direction information if using "inbound" or "outbound" instead
|
51
|
+
# of a direction tag.
|
52
|
+
direction = bus.send(direction.downcase.to_sym).id if direction =~ /(inbound|outbound)/i
|
53
|
+
|
54
|
+
# Create the stop object from the route, direction, and tag.
|
55
|
+
stop = Muni::Stop.new({:route_tag => route, :direction => direction, :tag => stop})
|
56
|
+
|
57
|
+
# Retrieve the predictions
|
58
|
+
begin
|
59
|
+
print_table stop.predictions.collect{|time| [time.vehicle, time.pretty_time]}, {:ident => 8}
|
60
|
+
rescue Muni::NextBusError => e
|
61
|
+
say_status "ERROR", e.message, :red
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
MUNI.start
|
data/lib/muni.rb
ADDED
data/lib/muni/base.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'mash'
|
2
|
+
module Muni
|
3
|
+
class NextBusError < StandardError; end
|
4
|
+
class Base < Mash
|
5
|
+
class << self
|
6
|
+
private
|
7
|
+
def fetch(command, options = nil)
|
8
|
+
url = build_url(command, options)
|
9
|
+
xml = Net::HTTP.get(URI.parse(url))
|
10
|
+
doc = XmlSimple.xml_in(xml)
|
11
|
+
fail NextBusError, doc['Error'].first['content'].gsub(/\n/,'') if doc['Error']
|
12
|
+
doc
|
13
|
+
end
|
14
|
+
|
15
|
+
def build_url(command, options = nil)
|
16
|
+
url = "http://webservices.nextbus.com/service/publicXMLFeed?command=%s&a=sf-muni" % command
|
17
|
+
if options
|
18
|
+
options.each { |key,value|
|
19
|
+
url << "&#{key}=#{value}"
|
20
|
+
}
|
21
|
+
end
|
22
|
+
url
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'action_view'
|
2
|
+
|
3
|
+
module Muni
|
4
|
+
class Prediction < Base
|
5
|
+
include ActionView::Helpers::DateHelper
|
6
|
+
def time
|
7
|
+
Time.at((epochTime.to_i / 1000.0).to_i)
|
8
|
+
end
|
9
|
+
|
10
|
+
def pretty_time
|
11
|
+
if time > Time.now
|
12
|
+
distance_of_time_in_words_to_now(time)
|
13
|
+
elsif time < Time.now
|
14
|
+
time_ago_in_words(time)
|
15
|
+
else
|
16
|
+
"Arriving"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/muni/route.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'xmlsimple'
|
3
|
+
|
4
|
+
require 'muni/stop'
|
5
|
+
require 'muni/direction'
|
6
|
+
|
7
|
+
module Muni
|
8
|
+
class Route < Base
|
9
|
+
def outbound
|
10
|
+
directions.select{|dir| dir.name =~ /outbound/i}.first
|
11
|
+
end
|
12
|
+
|
13
|
+
def inbound
|
14
|
+
directions.select{|dir| dir.name =~ /inbound/i}.first
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def find(tag)
|
19
|
+
if tag == :all
|
20
|
+
find_all
|
21
|
+
else
|
22
|
+
find_by_tag(tag)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def find_all
|
28
|
+
document = fetch(:routeList)
|
29
|
+
document['route'].collect do |el|
|
30
|
+
Route.new(el)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def find_by_tag(tag)
|
35
|
+
document = fetch(:routeConfig, {:r => tag})
|
36
|
+
route = Route.new({:tag => document['route'].first['tag'], :title => document['route'].first['title']})
|
37
|
+
|
38
|
+
stops = {}
|
39
|
+
|
40
|
+
document['route'].first['stop'].each do |stop|
|
41
|
+
st = Stop.new({
|
42
|
+
:tag => stop['tag'],
|
43
|
+
:title => stop['title'],
|
44
|
+
:lat => stop['lat'],
|
45
|
+
:lon => stop['lat'],
|
46
|
+
:stopId => stop['lat'],
|
47
|
+
})
|
48
|
+
stops[st[:tag]] = st
|
49
|
+
end
|
50
|
+
|
51
|
+
directions = []
|
52
|
+
route.directions = document['route'].first['direction'].collect do |direction|
|
53
|
+
direction_stops = direction['stop'].collect do |stop|
|
54
|
+
stops[stop['tag']]
|
55
|
+
end
|
56
|
+
|
57
|
+
direction_stops.each do |stop|
|
58
|
+
stop.route_tag = route.tag
|
59
|
+
stop.direction = direction['tag']
|
60
|
+
end
|
61
|
+
|
62
|
+
Direction.new({
|
63
|
+
:id => direction['tag'],
|
64
|
+
:name => direction['title'],
|
65
|
+
:stops => direction_stops
|
66
|
+
})
|
67
|
+
end
|
68
|
+
|
69
|
+
route
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/muni/stop.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'muni/base'
|
2
|
+
require 'muni/prediction'
|
3
|
+
|
4
|
+
module Muni
|
5
|
+
class Stop < Base
|
6
|
+
def predictions
|
7
|
+
document = Stop.send(:fetch, :predictions, {:r => route_tag, :d => direction, :s => tag})
|
8
|
+
document['predictions'].first['direction'].first['prediction'].collect do |pred|
|
9
|
+
Prediction.new(pred)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/muni/version.rb
ADDED
data/muni.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "muni/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "muni"
|
7
|
+
s.version = Muni::VERSION
|
8
|
+
s.authors = ["Jeff Remer"]
|
9
|
+
s.email = ["jeff@threestarchina.com"]
|
10
|
+
s.homepage = "http://jeffremer.com/muni"
|
11
|
+
s.summary = %q{NextBus San Francisco Muni API Client}
|
12
|
+
s.description = %q{A simple NextBus API client for retrieving San Francisco Muni bus route and stop prediction information}
|
13
|
+
|
14
|
+
s.rubyforge_project = "muni"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency "mash"
|
22
|
+
s.add_dependency "xml-simple"
|
23
|
+
s.add_dependency "actionpack"
|
24
|
+
s.add_dependency "amatch"
|
25
|
+
# For the executable
|
26
|
+
s.add_dependency "thor"
|
27
|
+
s.add_development_dependency "rspec", "~> 2.0.0.beta.22"
|
28
|
+
end
|
data/spec/route_spec.rb
ADDED
data/spec/stop_spec.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'muni/base'
|
2
|
+
require 'muni/route'
|
3
|
+
|
4
|
+
describe "Muni::Stop" do
|
5
|
+
it "#times fetches predictions" do
|
6
|
+
route = Muni::Route.find(21)
|
7
|
+
direction = route.directions.first
|
8
|
+
stop = direction.stops.first
|
9
|
+
times = stop.predictions
|
10
|
+
times.each do |time|
|
11
|
+
p time.pretty_time
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: muni
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jeff Remer
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-05-31 00:00:00.000000000 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: mash
|
17
|
+
requirement: &2152729760 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *2152729760
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: xml-simple
|
28
|
+
requirement: &2152729320 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *2152729320
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: actionpack
|
39
|
+
requirement: &2152728900 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
type: :runtime
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *2152728900
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: amatch
|
50
|
+
requirement: &2152728460 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
type: :runtime
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *2152728460
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: thor
|
61
|
+
requirement: &2152728000 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :runtime
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *2152728000
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rspec
|
72
|
+
requirement: &2152727420 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 2.0.0.beta.22
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: *2152727420
|
81
|
+
description: A simple NextBus API client for retrieving San Francisco Muni bus route
|
82
|
+
and stop prediction information
|
83
|
+
email:
|
84
|
+
- jeff@threestarchina.com
|
85
|
+
executables:
|
86
|
+
- muni
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- .gitignore
|
91
|
+
- Gemfile
|
92
|
+
- README.md
|
93
|
+
- Rakefile
|
94
|
+
- bin/muni
|
95
|
+
- lib/muni.rb
|
96
|
+
- lib/muni/base.rb
|
97
|
+
- lib/muni/direction.rb
|
98
|
+
- lib/muni/prediction.rb
|
99
|
+
- lib/muni/route.rb
|
100
|
+
- lib/muni/stop.rb
|
101
|
+
- lib/muni/version.rb
|
102
|
+
- muni.gemspec
|
103
|
+
- spec/route_spec.rb
|
104
|
+
- spec/stop_spec.rb
|
105
|
+
has_rdoc: true
|
106
|
+
homepage: http://jeffremer.com/muni
|
107
|
+
licenses: []
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
none: false
|
120
|
+
requirements:
|
121
|
+
- - ! '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
requirements: []
|
125
|
+
rubyforge_project: muni
|
126
|
+
rubygems_version: 1.6.2
|
127
|
+
signing_key:
|
128
|
+
specification_version: 3
|
129
|
+
summary: NextBus San Francisco Muni API Client
|
130
|
+
test_files:
|
131
|
+
- spec/route_spec.rb
|
132
|
+
- spec/stop_spec.rb
|