transilien_microservices 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.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +67 -0
- data/Guardfile +24 -0
- data/LICENSE.txt +22 -0
- data/README.md +91 -0
- data/Rakefile +1 -0
- data/lib/transilien/company.rb +2 -0
- data/lib/transilien/line.rb +18 -0
- data/lib/transilien/micro_service.rb +202 -0
- data/lib/transilien/mode.rb +5 -0
- data/lib/transilien/mode_type.rb +2 -0
- data/lib/transilien/network.rb +2 -0
- data/lib/transilien/route.rb +13 -0
- data/lib/transilien/stop.rb +27 -0
- data/lib/transilien/stop_area.rb +52 -0
- data/lib/transilien/stop_point.rb +41 -0
- data/lib/transilien/time.rb +20 -0
- data/lib/transilien/vehicle_journey.rb +26 -0
- data/lib/transilien/version.rb +3 -0
- data/lib/transilien_microservices.rb +22 -0
- data/spec/microservice_spec.rb +42 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/vehicle_journey_alone.xml +1 -0
- data/spec/vehicle_journey_spec.rb +14 -0
- data/transilien_microservices.gemspec +23 -0
- metadata +106 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: d9ce413dfd4786a986a8fe3226cef622df78e9f9
|
|
4
|
+
data.tar.gz: 3b672ac27a336f667d79fa1f73543d9012a84bb6
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0c673cb9635c16509f58f0829002111cfdf40302ff62d0252f5f27dac5ec6d393f171074e1d16096224d20cedcb7d9460608689fe5fd0e8265d594d6a8258253
|
|
7
|
+
data.tar.gz: 70b3ebb0084748339843dd5b64fd33b4cec56d5cf1c5f37be79a2b7062171b3b0b81d5104f63a6804641914ca1e829e4c9b4eba7fdc471e1546e37a34ab0be73
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.0.0-p0
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
transilien_microservices (0.0.1)
|
|
5
|
+
faraday (>= 0.8.4)
|
|
6
|
+
nokogiri (>= 1.5.5)
|
|
7
|
+
|
|
8
|
+
GEM
|
|
9
|
+
remote: https://rubygems.org/
|
|
10
|
+
specs:
|
|
11
|
+
celluloid (0.15.2)
|
|
12
|
+
timers (~> 1.1.0)
|
|
13
|
+
coderay (1.0.9)
|
|
14
|
+
diff-lcs (1.1.3)
|
|
15
|
+
faraday (0.8.4)
|
|
16
|
+
multipart-post (~> 1.1)
|
|
17
|
+
ffi (1.9.0)
|
|
18
|
+
formatador (0.2.4)
|
|
19
|
+
guard (2.1.1)
|
|
20
|
+
formatador (>= 0.2.4)
|
|
21
|
+
listen (~> 2.1)
|
|
22
|
+
lumberjack (~> 1.0)
|
|
23
|
+
pry (>= 0.9.12)
|
|
24
|
+
thor (>= 0.18.1)
|
|
25
|
+
guard-rspec (2.5.4)
|
|
26
|
+
guard (>= 1.1)
|
|
27
|
+
rspec (~> 2.11)
|
|
28
|
+
listen (2.1.1)
|
|
29
|
+
celluloid (>= 0.15.2)
|
|
30
|
+
rb-fsevent (>= 0.9.3)
|
|
31
|
+
rb-inotify (>= 0.9)
|
|
32
|
+
lumberjack (1.0.4)
|
|
33
|
+
method_source (0.8.2)
|
|
34
|
+
multipart-post (1.1.5)
|
|
35
|
+
nokogiri (1.5.9)
|
|
36
|
+
pry (0.9.12.2)
|
|
37
|
+
coderay (~> 1.0.5)
|
|
38
|
+
method_source (~> 0.8)
|
|
39
|
+
slop (~> 3.4)
|
|
40
|
+
pry-doc (0.4.6)
|
|
41
|
+
pry (>= 0.9)
|
|
42
|
+
yard (>= 0.8)
|
|
43
|
+
rb-fsevent (0.9.3)
|
|
44
|
+
rb-inotify (0.9.2)
|
|
45
|
+
ffi (>= 0.5.0)
|
|
46
|
+
rspec (2.12.0)
|
|
47
|
+
rspec-core (~> 2.12.0)
|
|
48
|
+
rspec-expectations (~> 2.12.0)
|
|
49
|
+
rspec-mocks (~> 2.12.0)
|
|
50
|
+
rspec-core (2.12.0)
|
|
51
|
+
rspec-expectations (2.12.0)
|
|
52
|
+
diff-lcs (~> 1.1.3)
|
|
53
|
+
rspec-mocks (2.12.0)
|
|
54
|
+
slop (3.4.6)
|
|
55
|
+
thor (0.18.1)
|
|
56
|
+
timers (1.1.0)
|
|
57
|
+
yard (0.8.7.2)
|
|
58
|
+
|
|
59
|
+
PLATFORMS
|
|
60
|
+
ruby
|
|
61
|
+
|
|
62
|
+
DEPENDENCIES
|
|
63
|
+
guard-rspec
|
|
64
|
+
pry
|
|
65
|
+
pry-doc
|
|
66
|
+
rspec
|
|
67
|
+
transilien_microservices!
|
data/Guardfile
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# A sample Guardfile
|
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
|
3
|
+
|
|
4
|
+
guard 'rspec' do
|
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
|
8
|
+
|
|
9
|
+
# Rails example
|
|
10
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
|
11
|
+
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
|
12
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
|
13
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
|
14
|
+
watch('config/routes.rb') { "spec/routing" }
|
|
15
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
|
16
|
+
|
|
17
|
+
# Capybara features specs
|
|
18
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
|
|
19
|
+
|
|
20
|
+
# Turnip features and steps
|
|
21
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
|
22
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
|
23
|
+
end
|
|
24
|
+
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2012-2013 Thomas Lecavelier
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# TransilienMicroservices
|
|
2
|
+
|
|
3
|
+
Ruby implementation of SNCF Transilien Microservices.
|
|
4
|
+
|
|
5
|
+
Here the original service documentation: http://test.data-sncf.com/index.php/transilien.html/api.22.22-micro-services.html
|
|
6
|
+
|
|
7
|
+
These services let you know the theoric offer on Transilien service.
|
|
8
|
+
|
|
9
|
+
Disclamer: The gem only intend to implements the API. I'll create a "easy" wrapper to access these data in a convenient way very soon.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
Gem developped with ruby 2.0.0, should work with ruby 1.9.3
|
|
14
|
+
|
|
15
|
+
Add this line to your application's Gemfile:
|
|
16
|
+
|
|
17
|
+
gem 'transilien_microservices'
|
|
18
|
+
|
|
19
|
+
And then execute:
|
|
20
|
+
|
|
21
|
+
$ bundle
|
|
22
|
+
|
|
23
|
+
Or install it yourself as:
|
|
24
|
+
|
|
25
|
+
$ gem install transilien_microservices
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
The best way to access data is certainly querying through StopArea: start by fetching them.
|
|
30
|
+
|
|
31
|
+
stop_areas = Transilien::StopArea.find
|
|
32
|
+
|
|
33
|
+
Every Transilien "main" objects have the same attributes:
|
|
34
|
+
|
|
35
|
+
stop_areas.first.inspect
|
|
36
|
+
=> "#<Transilien::StopArea external_code=\"DUA8738221\" name=\"LA DEFENSE GRANDE ARCHE\" >"
|
|
37
|
+
|
|
38
|
+
* "name" is a "public" name. Can't be filtered directly through Transilien API
|
|
39
|
+
* "external_code" is the true "key" to use in queries.
|
|
40
|
+
|
|
41
|
+
They have in bonus #payload method which return the node used to build this object.
|
|
42
|
+
|
|
43
|
+
If you want to find a commercial line that stops by two StopArea, say: Val d'Argenteuil (DUA8738179) and Paris Saint Lazare (DUA8738400) you can query this way:
|
|
44
|
+
|
|
45
|
+
val_stlaz_lines = Transilien::Line.find(stop_area_external_code: {and: ['DUA8738400', 'DUA8738179']})
|
|
46
|
+
|
|
47
|
+
Ok, but to tell the truth, I doubt that you don't bother about the way: you're going from Val to StLaz, not the inverse, so precise it:
|
|
48
|
+
|
|
49
|
+
val_to_stlaz_lines = Transilien::Line.find(destination_external_code: 'DUA8738400', stop_area_external_code: 'DUA8738179')
|
|
50
|
+
|
|
51
|
+
You get an Array of Transilien::Line fullfilling your wish.
|
|
52
|
+
|
|
53
|
+
Staying on that example, we'll stay with the "biggest" Line of the set: "Mantes la Jolie => Gare St Lazare via CONFLANS" DUA800854044
|
|
54
|
+
To get ALL the stops served by this Line:
|
|
55
|
+
|
|
56
|
+
Transilien::StopArea.find(line_external_code: 'DUA800854044')
|
|
57
|
+
|
|
58
|
+
Ok, that's fun. But Transilien is all about train and departures. What are the trains going from Val d’Argenteuil to Paris Saint Lazare? Transilien::VehicleJourney is all about it
|
|
59
|
+
|
|
60
|
+
instant = Time.new
|
|
61
|
+
start_time = Time.local(instant.year, instant.month, instant.day, 17, 30)
|
|
62
|
+
end_time = Time.local(instant.year, instant.month, instant.day, 18, 45)
|
|
63
|
+
Transilien::VehicleJourney.find stop_area_external_code: {and: ['DUA8738400', 'DUA8738179'], date: Transilien.date(instant), start_time: Transilien.time(start_time), end_time: Transilien.time(end_time) }
|
|
64
|
+
|
|
65
|
+
Yeah! Better. You still have a problem: this give you all the journey starting between start_time and end_time on date instant, but don't give a fuck to your way.
|
|
66
|
+
|
|
67
|
+
Ready to forget what you just learnt? Go back a little bit before this point: a Line instance always have at least two Route (one way, the other). And its finder understand a convenient param: CheckOrder. If set to 1, and 2 stops are given, Route returned will honor the given way by stops order:
|
|
68
|
+
|
|
69
|
+
routes_stlaz_val = Transilien::Route.find(stop_area_external_code: {and:['DUA8738400','DUA8738179']}, check_order: 1)
|
|
70
|
+
|
|
71
|
+
Here you have only Route stoping by DUA8738400 then DUA8738179, not the inverse.
|
|
72
|
+
|
|
73
|
+
Now it'll be easy to get VehicleJourney matching your needs. The same VehicleJourney will become:
|
|
74
|
+
|
|
75
|
+
Transilien::VehicleJourney.find route_external_code: routes_stlaz_val.map(&:external_code), date: Transilien.date(instant), start_time: Transilien.time(start_time), end_time: Transilien.time(end_time)
|
|
76
|
+
|
|
77
|
+
Easier, isn't it? Now take every Stop and keep only your matching StopArea: you'll get your hours of departures and arrivals :)
|
|
78
|
+
|
|
79
|
+
## Contributing
|
|
80
|
+
|
|
81
|
+
1. Fork it
|
|
82
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
83
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
84
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
85
|
+
5. Create new Pull Request
|
|
86
|
+
|
|
87
|
+
NOTA: you're a beginner gem dev? This command may help you:
|
|
88
|
+
|
|
89
|
+
pry -Ilib -rtransilien_microservices
|
|
90
|
+
|
|
91
|
+
(you can replace pry with irb if you're not a good person…)
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class Transilien::Line < Transilien::MicroService
|
|
2
|
+
def mode_type
|
|
3
|
+
@mode_type ||= Transilien::ModeType.from_node(payload.at('ModeType'), access_time)
|
|
4
|
+
end
|
|
5
|
+
def network
|
|
6
|
+
@network ||= Transilien::Network.from_node(payload.at('Network'), access_time)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# I don't have a clue what is about…
|
|
10
|
+
def forward
|
|
11
|
+
payload.at('Forward')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# I don't have a clue what is about…
|
|
15
|
+
def backward
|
|
16
|
+
payload.at('Backward')
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
require 'uri'
|
|
2
|
+
require 'faraday'
|
|
3
|
+
require 'nokogiri'
|
|
4
|
+
require 'time' # Time.parse for access_time in specialized instances
|
|
5
|
+
|
|
6
|
+
class Transilien::MicroService
|
|
7
|
+
API_HOST = 'ms.api.transilien.com'
|
|
8
|
+
API_URI = URI.parse("http://#{API_HOST}/")
|
|
9
|
+
|
|
10
|
+
attr_accessor :name
|
|
11
|
+
attr_accessor :external_code
|
|
12
|
+
|
|
13
|
+
attr_accessor :access_time
|
|
14
|
+
attr_accessor :payload
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
|
|
18
|
+
Default_cache_duration = 300 # in second
|
|
19
|
+
|
|
20
|
+
attr_accessor :caches
|
|
21
|
+
attr_accessor :query_cache
|
|
22
|
+
|
|
23
|
+
def http(uri = API_URI)
|
|
24
|
+
@http ||= Faraday.new(:url => uri) do |faraday|
|
|
25
|
+
# TODO give option to setup faraday
|
|
26
|
+
faraday.request :url_encoded # form-encode POST params
|
|
27
|
+
#faraday.response :logger # log requests to STDOUT
|
|
28
|
+
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def find_from_full_query_cache(filters)
|
|
33
|
+
@query_cache ||= {}
|
|
34
|
+
if filters[:force_refresh]
|
|
35
|
+
@query_cache.delete(filters.to_s)
|
|
36
|
+
end
|
|
37
|
+
if @query_cache[filters.to_s] && (@query_cache[filters.to_s][:cached_at].to_i + Default_cache_duration > Time.now.to_i)
|
|
38
|
+
return @query_cache[filters.to_s][:payload]
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Iterative search on per instance search. That's HARD.
|
|
43
|
+
# WIP idea: since filters are prefixed by operator (AND by default), we can deal key by key. Collection on the first run is the matching
|
|
44
|
+
# instances on that uniq key. The result will be the last collection returned. Potentially nil.
|
|
45
|
+
def find_from_query_caches(filters, collection = nil, operator = nil)
|
|
46
|
+
if collection.nil?
|
|
47
|
+
# FIRST RUN
|
|
48
|
+
filters.keys.each do |key|
|
|
49
|
+
collection = [query_cache({key: key, value: filters[key]})]
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# /?action=LineList&StopAreaExternalCode=DUA8754309;DUA8754513|and&RouteExternalCode=DUA8008030781013;DUA8008031050001|or
|
|
56
|
+
# -> find(:stop_area_external_code => { :and => ['DUA8754309', 'DUA8754513'] }, :route_external_code => { :or => ['DUA8008030781013', 'DUA8008031050001'] })
|
|
57
|
+
def find(filters = {}, options = {})
|
|
58
|
+
collection = find_from_full_query_cache(filters)
|
|
59
|
+
collection ||= find_from_query_caches(filters)
|
|
60
|
+
|
|
61
|
+
self.filters = filters
|
|
62
|
+
response = self.http.get(action_param, params)
|
|
63
|
+
puts('== Request: ')
|
|
64
|
+
puts(action_param.inspect)
|
|
65
|
+
puts(params.inspect)
|
|
66
|
+
puts(response.env[:url].inspect)
|
|
67
|
+
body = response.body
|
|
68
|
+
collection = []
|
|
69
|
+
doc = Nokogiri.XML(body)
|
|
70
|
+
return errors(doc) unless errors(doc).empty?
|
|
71
|
+
request_time = Time.parse(response.headers[:date])
|
|
72
|
+
doc.xpath(action_instance_xpath).each do |node|
|
|
73
|
+
item = from_node(node, request_time)
|
|
74
|
+
collection << item
|
|
75
|
+
end
|
|
76
|
+
@query_cache[filters.to_s] = { payload: collection, cached_at: request_time }
|
|
77
|
+
collection
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def from_node(node, access_time)
|
|
81
|
+
item = new
|
|
82
|
+
item.payload = node
|
|
83
|
+
|
|
84
|
+
# common stuff
|
|
85
|
+
item.external_code = node["#{action_component}ExternalCode"]
|
|
86
|
+
item.name = node["#{action_component}Name"]
|
|
87
|
+
item.access_time = access_time
|
|
88
|
+
|
|
89
|
+
cache_it(item)
|
|
90
|
+
|
|
91
|
+
item
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def cache_keys
|
|
95
|
+
[:name, :external_code]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def cache_it(item)
|
|
99
|
+
@caches ||= {}
|
|
100
|
+
cache_keys.each do |k|
|
|
101
|
+
@caches[k] ||= {}
|
|
102
|
+
@caches[k][item.send(k)] = item
|
|
103
|
+
end
|
|
104
|
+
item
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def query_cache(query = nil)
|
|
108
|
+
return @caches unless query
|
|
109
|
+
q = query || {}
|
|
110
|
+
q[:key] ||= 'name'
|
|
111
|
+
return nil if @caches.nil? || @caches[action_component].nil?
|
|
112
|
+
(@caches[action_component][q[:key]] || []).each do |item|
|
|
113
|
+
return item if item.name == q[:value]
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def errors(doc)
|
|
118
|
+
@errors ||= begin
|
|
119
|
+
@errors = []
|
|
120
|
+
doc.xpath('/Errors/Error').each do |err_node|
|
|
121
|
+
err = Transilien::MicroService::Error.new
|
|
122
|
+
err.code = err_node['code']
|
|
123
|
+
err.message = err_node.content
|
|
124
|
+
err.request = { params: params, action: action_param}
|
|
125
|
+
@errors << err
|
|
126
|
+
end
|
|
127
|
+
@errors
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def action_component
|
|
133
|
+
self.to_s.split('::').last
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def action
|
|
137
|
+
"#{action_component}List"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def action_param
|
|
141
|
+
"/?action=#{action}"
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def action_instance_xpath
|
|
145
|
+
"/Action#{action}/#{action}/#{action_component}"
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def params
|
|
149
|
+
return {} if filters.empty?
|
|
150
|
+
final = {}
|
|
151
|
+
@filters.each do |filter, filter_value|
|
|
152
|
+
final_filter = filter.to_s.split('_').map(&:capitalize).join
|
|
153
|
+
if filter_value.is_a?(Hash)
|
|
154
|
+
filter_value.each_pair do |operator, values|
|
|
155
|
+
ok_operators = [:and, :or]
|
|
156
|
+
raise ArgumentError.new("Operator #{operator} unknown. Should be one of #{ok_operators.inspect}.") unless ok_operators.include?(operator.to_sym)
|
|
157
|
+
final_values = [values].flatten.compact.join(';')
|
|
158
|
+
final[final_filter] = "#{final_values}|#{operator.to_s}"
|
|
159
|
+
end
|
|
160
|
+
elsif filter_value.is_a?(Array)
|
|
161
|
+
# By default, consider OR operator when values are only an array
|
|
162
|
+
final[final_filter] = "#{filter_value.join(';')}|or"
|
|
163
|
+
else
|
|
164
|
+
final[final_filter] = filter_value
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
final
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def filters
|
|
171
|
+
@filters ||= {}
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def filters=(new_filters)
|
|
175
|
+
raise ArgumentError.new('filters= -> new_filters MUST be a hash, even empty') unless new_filters.is_a?(Hash)
|
|
176
|
+
@filters = new_filters
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def add_filters()
|
|
180
|
+
self.filters
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def to_s
|
|
186
|
+
"#<#{self.class.to_s} external_code=#{@external_code.inspect} name=#{@name.inspect} >"
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
class Error
|
|
190
|
+
attr_accessor :code, :message, :payload, :request
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
class Transilien::FakeMicroService < Transilien::MicroService
|
|
196
|
+
|
|
197
|
+
class << self
|
|
198
|
+
def http(dummy=nil)
|
|
199
|
+
raise "FakeMicroService: you can't request a connection a connection. Use #from_node instead"
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class Transilien::Route < Transilien::MicroService
|
|
2
|
+
def line
|
|
3
|
+
@line ||= Transilien::Line.from_node(payload.at('Line'), access_time)
|
|
4
|
+
end
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class Transilien::City < Transilien::FakeMicroService
|
|
8
|
+
attr_accessor :code
|
|
9
|
+
def from_node(node, access_time)
|
|
10
|
+
item = super(node, access_time)
|
|
11
|
+
item.code(node['CityCode'])
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
class Transilien::Stop < Transilien::FakeMicroService
|
|
2
|
+
attr_accessor :stop_time, :arrival_time, :name_at_stop
|
|
3
|
+
|
|
4
|
+
class << self
|
|
5
|
+
def from_node(node, access_time)
|
|
6
|
+
item = new
|
|
7
|
+
item.payload = node
|
|
8
|
+
|
|
9
|
+
stop_node = node.at('StopTime')
|
|
10
|
+
item.stop_time = !stop_node.children.empty? && ::Transilien::Time.from_node(stop_node, access_time)
|
|
11
|
+
|
|
12
|
+
arrival_node = node.at('StopArrivalTime')
|
|
13
|
+
item.arrival_time = !arrival_node.children.empty? && ::Transilien::Time.from_node(arrival_node, access_time)
|
|
14
|
+
|
|
15
|
+
item.name_at_stop = node.at('VehicleJourneyNameAtStop') && node.at('VehicleJourneyNameAtStop').text
|
|
16
|
+
item
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def stop_point
|
|
21
|
+
@stop_point ||= Transilien::StopPoint.from_node(payload.at('StopPoint'), access_time)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def name # objective: enable caching
|
|
25
|
+
"#{stop_time.name}||#{arrival_time.name}"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
class Transilien::StopArea < Transilien::MicroService
|
|
2
|
+
def main_stop_area
|
|
3
|
+
@main_stop_area ||= payload['MainStopArea'] == '1'
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def multi_modal
|
|
7
|
+
@multi_modal ||= payload['MultiModal'] == '1'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def car_park
|
|
11
|
+
@car_park ||= payload['CarPark'] == '1'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def main_connection
|
|
15
|
+
@main_connection ||= payload['MainConnection'] == '1'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def additional_data
|
|
19
|
+
@additional_data ||= payload['AdditionalData']
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def resa_rail_code
|
|
23
|
+
@resa_rail_code ||= payload['ResaRailCode']
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def coord
|
|
27
|
+
@coord ||= {
|
|
28
|
+
x: payload.at('Coord').at('CoordX').content.sub(',','.').to_f,
|
|
29
|
+
y: payload.at('Coord').at('CoordY').content.sub(',','.').to_f
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def modes
|
|
34
|
+
@modes ||= begin
|
|
35
|
+
modes = []
|
|
36
|
+
payload.at('ModeList').children.each do |mode|
|
|
37
|
+
modes << Transilien::ModeType.from_node(mode, access_time)
|
|
38
|
+
end
|
|
39
|
+
modes
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
alias_method :mode_types, :modes # ModeList ≠ ModeTypeList : bad naming from SNCF
|
|
43
|
+
|
|
44
|
+
def city
|
|
45
|
+
@city ||= Transilien::City.from_node(payload.at('City'), access_time)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def hangs
|
|
49
|
+
@hangs ||= payload.at('HangList').children
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
class Transilien::StopPoint < Transilien::MicroService
|
|
2
|
+
def fare_zone
|
|
3
|
+
@fare_zone ||= payload['FareZone']
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def address
|
|
7
|
+
payload.at('StopPointAddress')
|
|
8
|
+
end
|
|
9
|
+
alias_method :stop_point_address, :address
|
|
10
|
+
|
|
11
|
+
def equipment
|
|
12
|
+
@equipment ||= {
|
|
13
|
+
sheltered: (payload.at('Equipment')['Sheltered'] == 'True'),
|
|
14
|
+
mimp_access: (payload.at('Equipment')['MIPAccess'] == 'True'),
|
|
15
|
+
elevator: (payload.at('Equipment')['Elevator'] == 'True'),
|
|
16
|
+
escalator: (payload.at('Equipment')['Escalator'] == 'True'),
|
|
17
|
+
bike_accepted: (payload.at('Equipment')['BikeAccepted'] == 'True'),
|
|
18
|
+
bike_depot: (payload.at('Equipment')['BikeDepot'] == 'True')
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def mode
|
|
23
|
+
@mode ||= Transilien::Mode.from_node(payload.at('Mode'), access_time)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def city
|
|
27
|
+
@city ||= Transilien::City.from_node(payload.at('City'), access_time)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def stop_area
|
|
31
|
+
#@stop_area ||= Transilien::StopArea.from_node(payload.at('StopArea'), access_time)
|
|
32
|
+
@stop_area ||= Transilien::StopArea.find(stop_area_external_code: payload.at('StopArea')['StopAreaExternalCode']).first
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def coord
|
|
36
|
+
@coord ||= {
|
|
37
|
+
x: payload.at('Coord').at('CoordX').content.sub(',','.').to_f,
|
|
38
|
+
y: payload.at('Coord').at('CoordY').content.sub(',','.').to_f
|
|
39
|
+
}
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class Transilien::Time < Transilien::FakeMicroService
|
|
2
|
+
attr_accessor :total_seconds, :day, :hour, :minute
|
|
3
|
+
|
|
4
|
+
class << self
|
|
5
|
+
def from_node(node, access_time)
|
|
6
|
+
item = new
|
|
7
|
+
item.payload = node
|
|
8
|
+
|
|
9
|
+
item.total_seconds = node.at('TotalSeconds').text
|
|
10
|
+
item.day = node.at('Day').text
|
|
11
|
+
item.hour = node.at('Hour').text
|
|
12
|
+
item.minute = node.at('Minute').text
|
|
13
|
+
item
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def name # objective: enable caching
|
|
18
|
+
"#{day}:#{hour}:#{minutes}|#{total_seconds}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class Transilien::VehicleJourney < Transilien::MicroService
|
|
2
|
+
def route
|
|
3
|
+
@route ||= Transilien::Route.from_node(payload.at('Route'), access_time)
|
|
4
|
+
end
|
|
5
|
+
def mode
|
|
6
|
+
@mode ||= Transilien::Mode.from_node(payload.at('Mode'), access_time)
|
|
7
|
+
end
|
|
8
|
+
def company
|
|
9
|
+
@company ||= Transilien::Company.from_node(payload.at('Company'), access_time)
|
|
10
|
+
end
|
|
11
|
+
def vehicle
|
|
12
|
+
@vehicle ||= payload.at('Vehicle')
|
|
13
|
+
end
|
|
14
|
+
def validity_pattern
|
|
15
|
+
@validity_pattern ||= payload.at('ValidityPattern')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def stops
|
|
19
|
+
@stops ||= begin
|
|
20
|
+
stops_nodes = payload.at('StopList')
|
|
21
|
+
stops_nodes.children.map do |stop_node|
|
|
22
|
+
Transilien::Stop.from_node(stop_node, access_time)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require "./lib/transilien/version.rb"
|
|
2
|
+
require "./lib/transilien/micro_service.rb"
|
|
3
|
+
require "./lib/transilien/time.rb"
|
|
4
|
+
require "./lib/transilien/network.rb"
|
|
5
|
+
require "./lib/transilien/mode_type.rb"
|
|
6
|
+
require "./lib/transilien/line.rb"
|
|
7
|
+
require "./lib/transilien/route.rb"
|
|
8
|
+
require "./lib/transilien/stop_point.rb"
|
|
9
|
+
require "./lib/transilien/stop_area.rb"
|
|
10
|
+
require "./lib/transilien/vehicle_journey.rb"
|
|
11
|
+
require "./lib/transilien/mode.rb"
|
|
12
|
+
require "./lib/transilien/company.rb"
|
|
13
|
+
require "./lib/transilien/stop.rb"
|
|
14
|
+
|
|
15
|
+
module Transilien
|
|
16
|
+
def self.date(time)
|
|
17
|
+
time.strftime('%Y|%m|%d')
|
|
18
|
+
end
|
|
19
|
+
def self.time(time)
|
|
20
|
+
time.strftime('%H|%M')
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
describe Transilien::MicroService do
|
|
3
|
+
it 'should generate empty params for nothing' do
|
|
4
|
+
Transilien::MicroService.filters = {}
|
|
5
|
+
Transilien::MicroService.params.empty?.should eq(true)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it 'should generate correct params for one simple filter' do
|
|
9
|
+
Transilien::MicroService.filters = {:network_external_code => 'DU804'}
|
|
10
|
+
Transilien::MicroService.params.should eq({'NetworkExternalCode' => 'DU804'})
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'should generate correct params for two simple filters' do
|
|
14
|
+
Transilien::MicroService.filters = {:network_external_code => 'DU804', :route_external_code => 'DUA8008030781013'}
|
|
15
|
+
Transilien::MicroService.params.should eq({'NetworkExternalCode' => 'DU804', 'RouteExternalCode' => 'DUA8008030781013'})
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'should generate correct params for one simple filter with Array, or is the default logic operator for arrays' do
|
|
19
|
+
Transilien::MicroService.filters = {:network_external_code => ['DU804', 'DU805']}
|
|
20
|
+
Transilien::MicroService.params.should eq({'NetworkExternalCode' => 'DU804;DU805|or'})
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should generate correct params for two simple filters with Array, or is the default logic operator for arrays' do
|
|
24
|
+
Transilien::MicroService.filters = {:network_external_code => ['DU804', 'DU805'], :route_external_code => ['DUA8008030781013', 'DUA8008031050001']}
|
|
25
|
+
Transilien::MicroService.params.should eq({'NetworkExternalCode' => 'DU804;DU805|or', 'RouteExternalCode' => 'DUA8008030781013;DUA8008031050001|or'})
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'should generate correct params for one complex filter' do
|
|
29
|
+
Transilien::MicroService.filters = {:network_external_code => { :and => ['DU804', 'DU805']}}
|
|
30
|
+
Transilien::MicroService.params.should eq({'NetworkExternalCode' => 'DU804;DU805|and'})
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'should generate correct params for two complex filters' do
|
|
34
|
+
Transilien::MicroService.filters = {:network_external_code => { :and => ['DU804', 'DU805']}, :route_external_code => { :or => ['DUA8008030781013', 'DUA8008031050001']}}
|
|
35
|
+
Transilien::MicroService.params.should eq({'NetworkExternalCode' => 'DU804;DU805|and', 'RouteExternalCode' => 'DUA8008030781013;DUA8008031050001|or'})
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'shoud generate correct params for a complex filter and a simple one' do
|
|
39
|
+
Transilien::MicroService.filters = {:stop_area_external_code => { :and => ['DUA8738400', 'DUA8738179']}, date: '2013|12|19', start_time: '17|00', end_time: '22|30'}
|
|
40
|
+
Transilien::MicroService.params.should eq({'StopAreaExternalCode' => 'DUA8738400;DUA8738179|and', 'Date' => '2013|12|19', 'StartTime' => '17|00', 'EndTime' => '22|30'})
|
|
41
|
+
end
|
|
42
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="ISO-8859-1"?><ActionVehicleJourneyList><Params Function="api"><SafeMode>0</SafeMode><action>PTReferential</action><RequestedType>vehiclejourneylist</RequestedType><routeexternalcode>DUA8008540420003;DUA8008540430008;DUA8008540430010;DUA8008540430005;DUA8008544000030;DUA8008540440001|or</routeexternalcode><date>2013|10|24</date><starttime>18|19</starttime><endtime>18|21</endtime><networkexternalcode>dua801;dua802;dua803;dua804;dua805;dua850;dua851;dua852;dua853;dua854;dua855</networkexternalcode><interface>1_10</interface><login>opendata</login></Params><VehicleJourneyList VehicleJourneyCount="1"><VehicleJourney VehicleJourneyIdx="391578" VehicleJourneyId="391577" VehicleJourneyName="GETO" VehicleJourneyRouteIdx="9991" VehicleJourneyExternalCode="DUASN137131F01002" IsAdapted="0"><Route RouteIdx="9991" RouteId="9990" RouteName="Gare St Lazare => Gisors Via Montgeroult" RouteExternalCode="DUA8008540430010" IsForward="1" RouteLineIdx="1660" IsFrequence="0" IsAdapted="0"><Line LineIdx="1660" LineId="1659" LineName="Gare St Lazare => Gisors Via Montgeroult" LineCode="J" LineExternalCode="DUA800854043" LineAdditionalData="" SortOrder="1660" LineColor="000000" HasAdaptedRoute="0"><ModeType ModeTypeIdx="15" ModeTypeExternalCode="RapidTransit" ModeTypeName="Train de banlieue / RER"/><Network NetworkIdx="76" NetworkId="8" NetworkName="Paris St Lazare" NetworkExternalCode="DUA854"></Network><Forward ForwardName="A"></Forward><Backward BackwardName=""></Backward></Line></Route><Mode ModeIdx="12" ModeId="12" ModeName="Train" ModeExternalCode="Train" ModeTypeExternalCode="RapidTransit"/><Company CompanyIdx="50" CompanyId="49" CompanyName="SNCF" CompanyExternalCode="DUA800"/><Vehicle VehicleIdx="0" VehicleId="-1" VehicleName="" VehicleExternalCode="" MIPAccess="False" BikeAccepted="False" AirConditioned="False"/><ValidityPattern ValidityPatternBeginningDay="2013|09|27" IsAdapted="0" ValidityPatternIdx="9987">000000000000000000000100111110011110001111100011110011111001111100111110011111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</ValidityPattern><StopList StopCount="15"><Stop StopIdx="6981526" StopPointIdx="1889" VehicleJourneyIdx="391578" HourNumber="0" MinuteNumber="0" DestinationPos="-1" ODTIdx="0" ODTPos="-1" ValidityPatternSetCommentPos="0" StopOrder="0" VehicleIdx="0"><StopTime><TotalSeconds>66000</TotalSeconds><Day>0</Day><Hour>18</Hour><Minute>20</Minute></StopTime><StopArrivalTime/><StopPoint StopPointIdx="1889" StopPointId="39699" StopPointName="PARIS SAINT-LAZARE" StopPointExternalCode="DUA8738400" FareZone="1"><StopPointAddress StopPointAddressName="" StopPointAddressNumber="" StopPointAddressTypeName=""/><Equipment Sheltered="False" MIPAccess="False" Elevator="False" Escalator="False" BikeAccepted="False" BikeDepot="False"/><Mode ModeIdx="12" ModeId="12" ModeName="Train" ModeExternalCode="Train" ModeTypeExternalCode="RapidTransit"/><City CityIdx="1" CityId="0" CityName="Paris" CityExternalCode="75056" CityCode="75004"></City><StopArea StopAreaIdx="592" StopAreaId="317" StopAreaName="PARIS SAINT-LAZARE" StopAreaExternalCode="DUA8738400" MainStopArea="1" MultiModal="0" CarPark="0" MainConnection="1" AdditionalData="" ResaRailCode=""><Coord><CoordX>599136,94</CoordX><CoordY>2430773,22</CoordY></Coord></StopArea><Coord><CoordX>599140,00</CoordX><CoordY>2430792,00</CoordY></Coord></StopPoint><VehicleJourneyNameAtStop>37131</VehicleJourneyNameAtStop></Stop><Stop StopIdx="7162918" StopPointIdx="39148" VehicleJourneyIdx="391578" HourNumber="0" MinuteNumber="0" DestinationPos="-1" ODTIdx="0" ODTPos="-1" ValidityPatternSetCommentPos="0" StopOrder="1" VehicleIdx="0"><StopTime><TotalSeconds>66960</TotalSeconds><Day>0</Day><Hour>18</Hour><Minute>36</Minute></StopTime><StopArrivalTime><TotalSeconds>66900</TotalSeconds><Day>0</Day><Hour>18</Hour><Minute>35</Minute></StopArrivalTime><StopPoint StopPointIdx="39148" StopPointId="39671" StopPointName="HERBLAY" StopPointExternalCode="DUA8738188" FareZone="4"><StopPointAddress StopPointAddressName="" StopPointAddressNumber="" StopPointAddressTypeName=""/><Equipment Sheltered="False" MIPAccess="False" Elevator="False" Escalator="False" BikeAccepted="False" BikeDepot="False"/><Mode ModeIdx="3" ModeId="3" ModeName="BUS" ModeExternalCode="RATP" ModeTypeExternalCode="Bus"/><City CityIdx="1185" CityId="1184" CityName="Herblay" CityExternalCode="95306" CityCode="95220"></City><StopArea StopAreaIdx="16806" StopAreaId="17633" StopAreaName="HERBLAY" StopAreaExternalCode="DUA8738188" MainStopArea="1" MultiModal="0" CarPark="0" MainConnection="0" AdditionalData="" ResaRailCode=""><Coord><CoordX>587165,67</CoordX><CoordY>2443663,10</CoordY></Coord></StopArea><Coord><CoordX>587212,66</CoordX><CoordY>2443585,69</CoordY></Coord></StopPoint></Stop><Stop StopIdx="7219144" StopPointIdx="13263" VehicleJourneyIdx="391578" HourNumber="0" MinuteNumber="0" DestinationPos="-1" ODTIdx="0" ODTPos="-1" ValidityPatternSetCommentPos="0" StopOrder="2" VehicleIdx="0"><StopTime><TotalSeconds>67260</TotalSeconds><Day>0</Day><Hour>18</Hour><Minute>41</Minute></StopTime><StopArrivalTime><TotalSeconds>67200</TotalSeconds><Day>0</Day><Hour>18</Hour><Minute>40</Minute></StopArrivalTime><StopPoint StopPointIdx="13263" StopPointId="39672" StopPointName="CONFLANS SAINTE-HONORINE" StopPointExternalCode="DUA8738189" FareZone="5"><StopPointAddress StopPointAddressName="" StopPointAddressNumber="" StopPointAddressTypeName=""/><Equipment Sheltered="False" MIPAccess="False" Elevator="False" Escalator="False" BikeAccepted="False" BikeDepot="False"/><Mode ModeIdx="3" ModeId="3" ModeName="BUS" ModeExternalCode="RATP" ModeTypeExternalCode="Bus"/><City CityIdx="579" CityId="578" CityName="Conflans-Sainte-Honorine" CityExternalCode="78172" CityCode="78700"></City><StopArea StopAreaIdx="5848" StopAreaId="6101" StopAreaName="CONFLANS SAINTE-HONORINE" StopAreaExternalCode="DUA8738189" MainStopArea="1" MultiModal="0" CarPark="0" MainConnection="0" AdditionalData="" ResaRailCode=""><Coord><CoordX>582543,85</CoordX><CoordY>2444390,69</CoordY></Coord></StopArea><Coord><CoordX>582518,32</CoordX><CoordY>2444303,58</CoordY></Coord></StopPoint></Stop><Stop StopIdx="7307988" StopPointIdx="40167" VehicleJourneyIdx="391578" HourNumber="0" MinuteNumber="0" DestinationPos="-1" ODTIdx="0" ODTPos="-1" ValidityPatternSetCommentPos="0" StopOrder="3" VehicleIdx="0"><StopTime><TotalSeconds>67740</TotalSeconds><Day>0</Day><Hour>18</Hour><Minute>49</Minute></StopTime><StopArrivalTime><TotalSeconds>67680</TotalSeconds><Day>0</Day><Hour>18</Hour><Minute>48</Minute></StopArrivalTime><StopPoint StopPointIdx="40167" StopPointId="39565" StopPointName="PONTOISE" StopPointExternalCode="DUA8727613" FareZone="5"><StopPointAddress StopPointAddressName="" StopPointAddressNumber="" StopPointAddressTypeName=""/><Equipment Sheltered="False" MIPAccess="False" Elevator="False" Escalator="False" BikeAccepted="False" BikeDepot="False"/><Mode ModeIdx="3" ModeId="3" ModeName="BUS" ModeExternalCode="RATP" ModeTypeExternalCode="Bus"/><City CityIdx="1236" CityId="1235" CityName="Pontoise" CityExternalCode="95500" CityCode="95300"></City><StopArea StopAreaIdx="17260" StopAreaId="18082" StopAreaName="PONTOISE" StopAreaExternalCode="DUA8727613" MainStopArea="1" MultiModal="0" CarPark="0" MainConnection="1" AdditionalData="" ResaRailCode=""><Coord><CoordX>582304,73</CoordX><CoordY>2449874,50</CoordY></Coord></StopArea><Coord><CoordX>582346,60</CoordX><CoordY>2449869,95</CoordY></Coord></StopPoint></Stop><Stop StopIdx="7352269" StopPointIdx="39920" VehicleJourneyIdx="391578" HourNumber="0" MinuteNumber="0" DestinationPos="-1" ODTIdx="0" ODTPos="-1" ValidityPatternSetCommentPos="0" StopOrder="4" VehicleIdx="0"><StopTime><TotalSeconds>67980</TotalSeconds><Day>0</Day><Hour>18</Hour><Minute>53</Minute></StopTime><StopArrivalTime><TotalSeconds>67980</TotalSeconds><Day>0</Day><Hour>18</Hour><Minute>53</Minute></StopArrivalTime><StopPoint StopPointIdx="39920" StopPointId="39632" StopPointName="OSNY" StopPointExternalCode="DUA8738114" FareZone="5"><StopPointAddress StopPointAddressName="" StopPointAddressNumber="" StopPointAddressTypeName=""/><Equipment Sheltered="False" MIPAccess="False" Elevator="False" Escalator="False" BikeAccepted="False" BikeDepot="False"/><Mode ModeIdx="12" ModeId="12" ModeName="Train" ModeExternalCode="Train" ModeTypeExternalCode="RapidTransit"/><City CityIdx="1227" CityId="1226" CityName="Osny" CityExternalCode="95476" CityCode="95520"></City><StopArea StopAreaIdx="17177" StopAreaId="18009" StopAreaName="OSNY" StopAreaExternalCode="DUA8738114" MainStopArea="1" MultiModal="0" CarPark="0" MainConnection="0" AdditionalData="" ResaRailCode=""><Coord><CoordX>579578,22</CoordX><CoordY>2451707,92</CoordY></Coord></StopArea><Coord><CoordX>579625,09</CoordX><CoordY>2451695,58</CoordY></Coord></StopPoint></Stop><Stop StopIdx="7395775" StopPointIdx="37513" VehicleJourneyIdx="391578" HourNumber="0" MinuteNumber="0" DestinationPos="-1" ODTIdx="0" ODTPos="-1" ValidityPatternSetCommentPos="0" StopOrder="5" VehicleIdx="0"><StopTime><TotalSeconds>68220</TotalSeconds><Day>0</Day><Hour>18</Hour><Minute>57</Minute></StopTime><StopArrivalTime><TotalSeconds>68220</TotalSeconds><Day>0</Day><Hour>18</Hour><Minute>57</Minute></StopArrivalTime><StopPoint StopPointIdx="37513" StopPointId="39633" StopPointName="BOISSY L'AILLERIE" StopPointExternalCode="DUA8738115" FareZone="5"><StopPointAddress StopPointAddressName="" StopPointAddressNumber="" StopPointAddressTypeName=""/><Equipment Sheltered="False" MIPAccess="False" Elevator="False" Escalator="False" BikeAccepted="False" BikeDepot="False"/><Mode ModeIdx="12" ModeId="12" ModeName="Train" ModeExternalCode="Train" ModeTypeExternalCode="RapidTransit"/><City CityIdx="1123" CityId="1122" CityName="Boissy-l'Aillerie" CityExternalCode="95078" CityCode="95650"></City><StopArea StopAreaIdx="16097" StopAreaId="16902" StopAreaName="BOISSY L'AILLERIE" StopAreaExternalCode="DUA8738115" MainStopArea="1" MultiModal="0" CarPark="0" MainConnection="0" AdditionalData="" ResaRailCode=""><Coord><CoordX>577234,07</CoordX><CoordY>2453083,08</CoordY></Coord></StopArea><Coord><CoordX>577221,21</CoordX><CoordY>2453137,24</CoordY></Coord></StopPoint></Stop><Stop StopIdx="7428308" StopPointIdx="39612" VehicleJourneyIdx="391578" HourNumber="0" MinuteNumber="0" DestinationPos="-1" ODTIdx="0" ODTPos="-1" ValidityPatternSetCommentPos="0" StopOrder="6" VehicleIdx="0"><StopTime><TotalSeconds>68400</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>00</Minute></StopTime><StopArrivalTime><TotalSeconds>68400</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>00</Minute></StopArrivalTime><StopPoint StopPointIdx="39612" StopPointId="39634" StopPointName="MONTGEROULT COURCELLES" StopPointExternalCode="DUA8738116" FareZone="5"><StopPointAddress StopPointAddressName="" StopPointAddressNumber="" StopPointAddressTypeName=""/><Equipment Sheltered="False" MIPAccess="False" Elevator="False" Escalator="False" BikeAccepted="False" BikeDepot="False"/><Mode ModeIdx="12" ModeId="12" ModeName="Train" ModeExternalCode="Train" ModeTypeExternalCode="RapidTransit"/><City CityIdx="1210" CityId="1209" CityName="Montgeroult" CityExternalCode="95422" CityCode="95650"></City><StopArea StopAreaIdx="17040" StopAreaId="17878" StopAreaName="MONTGEROULT COURCELLES" StopAreaExternalCode="DUA8738116" MainStopArea="1" MultiModal="0" CarPark="0" MainConnection="0" AdditionalData="" ResaRailCode=""><Coord><CoordX>575713,63</CoordX><CoordY>2453675,60</CoordY></Coord></StopArea><Coord><CoordX>575670,74</CoordX><CoordY>2453661,18</CoordY></Coord></StopPoint></Stop><Stop StopIdx="7471886" StopPointIdx="41239" VehicleJourneyIdx="391578" HourNumber="0" MinuteNumber="0" DestinationPos="-1" ODTIdx="0" ODTPos="-1" ValidityPatternSetCommentPos="0" StopOrder="7" VehicleIdx="0"><StopTime><TotalSeconds>68640</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>04</Minute></StopTime><StopArrivalTime><TotalSeconds>68640</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>04</Minute></StopArrivalTime><StopPoint StopPointIdx="41239" StopPointId="39635" StopPointName="US" StopPointExternalCode="DUA8738117" FareZone="5"><StopPointAddress StopPointAddressName="" StopPointAddressNumber="" StopPointAddressTypeName=""/><Equipment Sheltered="False" MIPAccess="False" Elevator="False" Escalator="False" BikeAccepted="False" BikeDepot="False"/><Mode ModeIdx="12" ModeId="12" ModeName="Train" ModeExternalCode="Train" ModeTypeExternalCode="RapidTransit"/><City CityIdx="1265" CityId="1264" CityName="Us" CityExternalCode="95625" CityCode="95450"></City><StopArea StopAreaIdx="17670" StopAreaId="18535" StopAreaName="US" StopAreaExternalCode="DUA8738117" MainStopArea="1" MultiModal="0" CarPark="0" MainConnection="0" AdditionalData="" ResaRailCode=""><Coord><CoordX>573255,15</CoordX><CoordY>2455803,84</CoordY></Coord></StopArea><Coord><CoordX>573255,15</CoordX><CoordY>2455803,84</CoordY></Coord></StopPoint></Stop><Stop StopIdx="7514946" StopPointIdx="40851" VehicleJourneyIdx="391578" HourNumber="0" MinuteNumber="0" DestinationPos="-1" ODTIdx="0" ODTPos="-1" ValidityPatternSetCommentPos="0" StopOrder="8" VehicleIdx="0"><StopTime><TotalSeconds>68880</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>08</Minute></StopTime><StopArrivalTime><TotalSeconds>68880</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>08</Minute></StopArrivalTime><StopPoint StopPointIdx="40851" StopPointId="39636" StopPointName="SANTEUIL LE PERCHAY" StopPointExternalCode="DUA8738118" FareZone="5"><StopPointAddress StopPointAddressName="" StopPointAddressNumber="" StopPointAddressTypeName=""/><Equipment Sheltered="False" MIPAccess="False" Elevator="False" Escalator="False" BikeAccepted="False" BikeDepot="False"/><Mode ModeIdx="12" ModeId="12" ModeName="Train" ModeExternalCode="Train" ModeTypeExternalCode="RapidTransit"/><City CityIdx="1255" CityId="1254" CityName="Santeuil" CityExternalCode="95584" CityCode="95640"></City><StopArea StopAreaIdx="17515" StopAreaId="18374" StopAreaName="SANTEUIL LE PERCHAY" StopAreaExternalCode="DUA8738118" MainStopArea="1" MultiModal="0" CarPark="0" MainConnection="0" AdditionalData="" ResaRailCode=""><Coord><CoordX>571574,93</CoordX><CoordY>2458528,71</CoordY></Coord></StopArea><Coord><CoordX>571718,79</CoordX><CoordY>2458460,14</CoordY></Coord></StopPoint></Stop><Stop StopIdx="7567792" StopPointIdx="37934" VehicleJourneyIdx="391578" HourNumber="0" MinuteNumber="0" DestinationPos="-1" ODTIdx="0" ODTPos="-1" ValidityPatternSetCommentPos="0" StopOrder="9" VehicleIdx="0"><StopTime><TotalSeconds>69180</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>13</Minute></StopTime><StopArrivalTime><TotalSeconds>69120</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>12</Minute></StopArrivalTime><StopPoint StopPointIdx="37934" StopPointId="39637" StopPointName="CHARS" StopPointExternalCode="DUA8738119" FareZone="5"><StopPointAddress StopPointAddressName="" StopPointAddressNumber="" StopPointAddressTypeName=""/><Equipment Sheltered="False" MIPAccess="False" Elevator="False" Escalator="False" BikeAccepted="False" BikeDepot="False"/><Mode ModeIdx="12" ModeId="12" ModeName="Train" ModeExternalCode="Train" ModeTypeExternalCode="RapidTransit"/><City CityIdx="1137" CityId="1136" CityName="Chars" CityExternalCode="95142" CityCode="95750"></City><StopArea StopAreaIdx="16228" StopAreaId="17039" StopAreaName="CHARS" StopAreaExternalCode="DUA8738119" MainStopArea="1" MultiModal="0" CarPark="0" MainConnection="0" AdditionalData="" ResaRailCode=""><Coord><CoordX>570834,99</CoordX><CoordY>2462829,40</CoordY></Coord></StopArea><Coord><CoordX>570834,99</CoordX><CoordY>2462829,40</CoordY></Coord></StopPoint></Stop><Stop StopIdx="7620012" StopPointIdx="41587" VehicleJourneyIdx="391578" HourNumber="0" MinuteNumber="0" DestinationPos="-1" ODTIdx="0" ODTPos="-1" ValidityPatternSetCommentPos="0" StopOrder="10" VehicleIdx="0"><StopTime><TotalSeconds>69480</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>18</Minute></StopTime><StopArrivalTime><TotalSeconds>69420</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>17</Minute></StopArrivalTime><StopPoint StopPointIdx="41587" StopPointId="39638" StopPointName="LA VILLETERTRE" StopPointExternalCode="DUA8738120" FareZone="100"><StopPointAddress StopPointAddressName="" StopPointAddressNumber="" StopPointAddressTypeName=""/><Equipment Sheltered="False" MIPAccess="False" Elevator="False" Escalator="False" BikeAccepted="False" BikeDepot="False"/><Mode ModeIdx="12" ModeId="12" ModeName="Train" ModeExternalCode="Train" ModeTypeExternalCode="RapidTransit"/><City CityIdx="1321" CityId="1295" CityName="Lavilletertre" CityExternalCode="60356" CityCode="60240"></City><StopArea StopAreaIdx="17825" StopAreaId="18698" StopAreaName="LA VILLETERTRE" StopAreaExternalCode="DUA8738120" MainStopArea="1" MultiModal="0" CarPark="0" MainConnection="0" AdditionalData="" ResaRailCode=""><Coord><CoordX>569663,00</CoordX><CoordY>2467290,00</CoordY></Coord></StopArea><Coord><CoordX>569663,00</CoordX><CoordY>2467290,00</CoordY></Coord></StopPoint></Stop><Stop StopIdx="7661292" StopPointIdx="41590" VehicleJourneyIdx="391578" HourNumber="0" MinuteNumber="0" DestinationPos="-1" ODTIdx="0" ODTPos="-1" ValidityPatternSetCommentPos="0" StopOrder="11" VehicleIdx="0"><StopTime><TotalSeconds>69720</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>22</Minute></StopTime><StopArrivalTime><TotalSeconds>69660</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>21</Minute></StopArrivalTime><StopPoint StopPointIdx="41590" StopPointId="39639" StopPointName="LIANCOURT SAINT-PIERRE" StopPointExternalCode="DUA8738121" FareZone="100"><StopPointAddress StopPointAddressName="" StopPointAddressNumber="" StopPointAddressTypeName=""/><Equipment Sheltered="False" MIPAccess="False" Elevator="False" Escalator="False" BikeAccepted="False" BikeDepot="False"/><Mode ModeIdx="12" ModeId="12" ModeName="Train" ModeExternalCode="Train" ModeTypeExternalCode="RapidTransit"/><City CityIdx="1323" CityId="1296" CityName="Liancourt-Saint-Pierre" CityExternalCode="60361" CityCode="60240"></City><StopArea StopAreaIdx="17827" StopAreaId="18700" StopAreaName="LIANCOURT SAINT-PIERRE" StopAreaExternalCode="DUA8738121" MainStopArea="1" MultiModal="0" CarPark="0" MainConnection="0" AdditionalData="" ResaRailCode=""><Coord><CoordX>568562,00</CoordX><CoordY>2469312,00</CoordY></Coord></StopArea><Coord><CoordX>568562,00</CoordX><CoordY>2469312,00</CoordY></Coord></StopPoint></Stop><Stop StopIdx="7721453" StopPointIdx="41555" VehicleJourneyIdx="391578" HourNumber="0" MinuteNumber="0" DestinationPos="-1" ODTIdx="0" ODTPos="-1" ValidityPatternSetCommentPos="0" StopOrder="12" VehicleIdx="0"><StopTime><TotalSeconds>70080</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>28</Minute></StopTime><StopArrivalTime><TotalSeconds>70080</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>28</Minute></StopArrivalTime><StopPoint StopPointIdx="41555" StopPointId="39640" StopPointName="CHAUMONT EN VEXIN" StopPointExternalCode="DUA8738122" FareZone="100"><StopPointAddress StopPointAddressName="" StopPointAddressNumber="" StopPointAddressTypeName=""/><Equipment Sheltered="False" MIPAccess="False" Elevator="False" Escalator="False" BikeAccepted="False" BikeDepot="False"/><Mode ModeIdx="12" ModeId="12" ModeName="Train" ModeExternalCode="Train" ModeTypeExternalCode="RapidTransit"/><City CityIdx="1307" CityId="1290" CityName="Chaumont-en-Vexin" CityExternalCode="60143" CityCode="60240"></City><StopArea StopAreaIdx="17804" StopAreaId="18677" StopAreaName="CHAUMONT EN VEXIN" StopAreaExternalCode="DUA8738122" MainStopArea="1" MultiModal="0" CarPark="0" MainConnection="0" AdditionalData="" ResaRailCode=""><Coord><CoordX>566204,00</CoordX><CoordY>2473835,00</CoordY></Coord></StopArea><Coord><CoordX>566204,00</CoordX><CoordY>2473835,00</CoordY></Coord></StopPoint></Stop><Stop StopIdx="7771163" StopPointIdx="41679" VehicleJourneyIdx="391578" HourNumber="0" MinuteNumber="0" DestinationPos="-1" ODTIdx="0" ODTPos="-1" ValidityPatternSetCommentPos="0" StopOrder="13" VehicleIdx="0"><StopTime><TotalSeconds>70380</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>33</Minute></StopTime><StopArrivalTime><TotalSeconds>70380</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>33</Minute></StopArrivalTime><StopPoint StopPointIdx="41679" StopPointId="39641" StopPointName="TRIE CHATEAU" StopPointExternalCode="DUA8738123" FareZone="100"><StopPointAddress StopPointAddressName="" StopPointAddressNumber="" StopPointAddressTypeName=""/><Equipment Sheltered="False" MIPAccess="False" Elevator="False" Escalator="False" BikeAccepted="False" BikeDepot="False"/><Mode ModeIdx="12" ModeId="12" ModeName="Train" ModeExternalCode="Train" ModeTypeExternalCode="RapidTransit"/><City CityIdx="1346" CityId="1305" CityName="Trie-Ch�teau" CityExternalCode="60644" CityCode="60590"></City><StopArea StopAreaIdx="17884" StopAreaId="18760" StopAreaName="TRIE CHATEAU" StopAreaExternalCode="DUA8738123" MainStopArea="1" MultiModal="0" CarPark="0" MainConnection="0" AdditionalData="" ResaRailCode=""><Coord><CoordX>562249,00</CoordX><CoordY>2476227,00</CoordY></Coord></StopArea><Coord><CoordX>562249,00</CoordX><CoordY>2476227,00</CoordY></Coord></StopPoint></Stop><Stop StopIdx="7800949" StopPointIdx="41725" VehicleJourneyIdx="391578" HourNumber="0" MinuteNumber="0" DestinationPos="-1" ODTIdx="0" ODTPos="-1" ValidityPatternSetCommentPos="0" StopOrder="14" VehicleIdx="0"><StopTime><TotalSeconds>70560</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>36</Minute></StopTime><StopArrivalTime><TotalSeconds>70560</TotalSeconds><Day>0</Day><Hour>19</Hour><Minute>36</Minute></StopArrivalTime><StopPoint StopPointIdx="41725" StopPointId="39642" StopPointName="GISORS" StopPointExternalCode="DUA8738124" FareZone="100"><StopPointAddress StopPointAddressName="" StopPointAddressNumber="" StopPointAddressTypeName=""/><Equipment Sheltered="False" MIPAccess="False" Elevator="False" Escalator="False" BikeAccepted="False" BikeDepot="False"/><Mode ModeIdx="12" ModeId="12" ModeName="Train" ModeExternalCode="Train" ModeTypeExternalCode="RapidTransit"/><City CityIdx="1360" CityId="1309" CityName="Gisors" CityExternalCode="27284" CityCode="27140"></City><StopArea StopAreaIdx="17907" StopAreaId="18785" StopAreaName="GISORS" StopAreaExternalCode="DUA8738124" MainStopArea="1" MultiModal="0" CarPark="0" MainConnection="0" AdditionalData="" ResaRailCode=""><Coord><CoordX>559847,00</CoordX><CoordY>2476541,00</CoordY></Coord></StopArea><Coord><CoordX>559847,00</CoordX><CoordY>2476541,00</CoordY></Coord></StopPoint></Stop></StopList></VehicleJourney></VehicleJourneyList><PagerInfo ResponseCount="1" ResponseStartIndex="0" TotalCount="1"/></ActionVehicleJourneyList>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
raw_payload = %(
|
|
4
|
+
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
describe Transilien::MicroService do
|
|
8
|
+
it 'should get a set of Stop' do
|
|
9
|
+
# This payload was generated from
|
|
10
|
+
# http://ms.api.transilien.com/?action=VehicleJourneyList&RouteExternalCode=DUA8008540420003%3BDUA8008540430008%3BDUA8008540430010%3BDUA8008540430005%3BDUA8008544000030%3BDUA8008540440001|or&Date=2013|10|24&StartTime=18|19&EndTime=18|21
|
|
11
|
+
vj = Transilien::VehicleJourney.from_node(Nokogiri.XML((Pathname.new('spec') + 'vehicle_journey_alone.xml').read), Time.now)
|
|
12
|
+
vj.stops.first.class.should eql(Transilien::Stop)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'transilien/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |gem|
|
|
7
|
+
gem.name = "transilien_microservices"
|
|
8
|
+
gem.version = Transilien::VERSION
|
|
9
|
+
gem.authors = ["Thomas Lecavelier"]
|
|
10
|
+
gem.email = ["thomas-gems@lecavelier.name"]
|
|
11
|
+
gem.description = %q{Implements SNCF Transilien micro-services API: enable access to their theoric offer.}
|
|
12
|
+
gem.summary = %q{See http://test.data-sncf.com/index.php?p=transilien}
|
|
13
|
+
gem.homepage = "https://github.com/ook/transilien_microservices"
|
|
14
|
+
gem.license = 'MIT'
|
|
15
|
+
|
|
16
|
+
gem.add_runtime_dependency('faraday', '>= 0.8.4') # HTTP(S) connections
|
|
17
|
+
gem.add_runtime_dependency('nokogiri', '>= 1.5.5') # XML parsing
|
|
18
|
+
|
|
19
|
+
gem.files = `git ls-files`.split($/)
|
|
20
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
21
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
22
|
+
gem.require_paths = ["lib"]
|
|
23
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: transilien_microservices
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Thomas Lecavelier
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2013-10-29 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: faraday
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - '>='
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 0.8.4
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - '>='
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 0.8.4
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: nokogiri
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - '>='
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 1.5.5
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - '>='
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: 1.5.5
|
|
41
|
+
description: 'Implements SNCF Transilien micro-services API: enable access to their
|
|
42
|
+
theoric offer.'
|
|
43
|
+
email:
|
|
44
|
+
- thomas-gems@lecavelier.name
|
|
45
|
+
executables: []
|
|
46
|
+
extensions: []
|
|
47
|
+
extra_rdoc_files: []
|
|
48
|
+
files:
|
|
49
|
+
- .gitignore
|
|
50
|
+
- .rspec
|
|
51
|
+
- .ruby-version
|
|
52
|
+
- Gemfile
|
|
53
|
+
- Gemfile.lock
|
|
54
|
+
- Guardfile
|
|
55
|
+
- LICENSE.txt
|
|
56
|
+
- README.md
|
|
57
|
+
- Rakefile
|
|
58
|
+
- lib/transilien/company.rb
|
|
59
|
+
- lib/transilien/line.rb
|
|
60
|
+
- lib/transilien/micro_service.rb
|
|
61
|
+
- lib/transilien/mode.rb
|
|
62
|
+
- lib/transilien/mode_type.rb
|
|
63
|
+
- lib/transilien/network.rb
|
|
64
|
+
- lib/transilien/route.rb
|
|
65
|
+
- lib/transilien/stop.rb
|
|
66
|
+
- lib/transilien/stop_area.rb
|
|
67
|
+
- lib/transilien/stop_point.rb
|
|
68
|
+
- lib/transilien/time.rb
|
|
69
|
+
- lib/transilien/vehicle_journey.rb
|
|
70
|
+
- lib/transilien/version.rb
|
|
71
|
+
- lib/transilien_microservices.rb
|
|
72
|
+
- spec/microservice_spec.rb
|
|
73
|
+
- spec/spec_helper.rb
|
|
74
|
+
- spec/vehicle_journey_alone.xml
|
|
75
|
+
- spec/vehicle_journey_spec.rb
|
|
76
|
+
- transilien_microservices.gemspec
|
|
77
|
+
homepage: https://github.com/ook/transilien_microservices
|
|
78
|
+
licenses:
|
|
79
|
+
- MIT
|
|
80
|
+
metadata: {}
|
|
81
|
+
post_install_message:
|
|
82
|
+
rdoc_options: []
|
|
83
|
+
require_paths:
|
|
84
|
+
- lib
|
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - '>='
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
|
+
requirements:
|
|
92
|
+
- - '>='
|
|
93
|
+
- !ruby/object:Gem::Version
|
|
94
|
+
version: '0'
|
|
95
|
+
requirements: []
|
|
96
|
+
rubyforge_project:
|
|
97
|
+
rubygems_version: 2.0.0
|
|
98
|
+
signing_key:
|
|
99
|
+
specification_version: 4
|
|
100
|
+
summary: See http://test.data-sncf.com/index.php?p=transilien
|
|
101
|
+
test_files:
|
|
102
|
+
- spec/microservice_spec.rb
|
|
103
|
+
- spec/spec_helper.rb
|
|
104
|
+
- spec/vehicle_journey_alone.xml
|
|
105
|
+
- spec/vehicle_journey_spec.rb
|
|
106
|
+
has_rdoc:
|