gares 1.0.0 → 1.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 371e96298472d334dcfbce42c20bc6a67813139a
4
- data.tar.gz: 3dc98f7e626ed7d6092b912a8e3441047bffb0c3
3
+ metadata.gz: 5a7346ed6637e992bd4ce2dc1be20d8b1e44fcf8
4
+ data.tar.gz: 2d681f7d329983887a33aed98d6399fde4097c85
5
5
  SHA512:
6
- metadata.gz: 89a404991c7555b8c65ccfa57987f8e553b03f18c284be6a73536ab0ab3213e8060e32faafe29b2d4b8492c340d0ec8586ffe7cbf0b678ba8f71efe1485b69aa
7
- data.tar.gz: a19cc680b00bc2244cf8670e0c60e60c91a92e75a0bade68004abc8adfc6f3c9e90a58000cc25700b0186629cbf0de49969162831c34a5caff3b9c48e40bccb9
6
+ metadata.gz: ca67937fb6fdfc242aefebb4661e67f456fde6512463ee367cab41bf33a06d0be452b21e8e5a1002ad75c28b22f0f044209cab6b899560295917303feaedf34d
7
+ data.tar.gz: 58958615ac14299dbae8ee968e8ef22ce9e9eeaf71bfddcc5664412c214a118f480bba287e38df92ad20353e9c44684c96e8e578c643f580e315c1df0c04852b
data/README.md CHANGED
@@ -5,6 +5,7 @@
5
5
  ## Description
6
6
 
7
7
  The Gares gem allows you to easily access publicly available data from gares-en-mouvement.com.
8
+ It can also retrieve data from sncf.com for live train information.
8
9
 
9
10
  ## Features
10
11
 
@@ -12,6 +13,7 @@ Gares currently features the following:
12
13
 
13
14
  * Search for a station
14
15
  * Retrieve station information
16
+ * Search for a train to get live information about it
15
17
 
16
18
  ## Examples
17
19
 
@@ -34,6 +36,8 @@ Gares currently features the following:
34
36
  [g.lat, g.long]
35
37
  #=> [45.760281, 4.859801]
36
38
 
39
+ See the [`Gares::Base` class documentation](http://www.rubydoc.info/github/paulrbr/gares/master/Gares/Base) for all available data on a station.
40
+
37
41
  ### Searching:
38
42
 
39
43
  g = Gares::Search.new("Aix")
@@ -49,6 +53,30 @@ Gares currently features the following:
49
53
  station.name
50
54
  #=> "Paris Gare de Lyon"
51
55
 
56
+ ### Train information:
57
+
58
+ train = Gares::Train.new(11641, Time.now)
59
+
60
+ train.departure.station
61
+ #=> #<Gares::Station:0x000f0000000000 @slug="frpst", @name="Paris Est">
62
+
63
+ train.departure.departure_date
64
+ #=> 2015-04-25 06:42:00 +0200
65
+
66
+ train.stops.size
67
+ #=> 12
68
+
69
+ train.delayed?
70
+ #=> false
71
+
72
+ train.arrival.station.name
73
+ #=> "Culmont - Chalindrey"
74
+
75
+ train.arrival.platform
76
+ #=> "B"
77
+
78
+ See the [`Gares::Train` class documentation](http://www.rubydoc.info/github/paulrbr/gares/master/Gares/Train) for all available data on a train.
79
+
52
80
  ## Installation
53
81
 
54
82
  gem install gares
@@ -85,6 +113,8 @@ the fixture files once with up-to-date content:
85
113
 
86
114
  $ rake fixtures:refresh
87
115
 
116
+ __Warning: this will probably break some tests, in particular the live train information tests.__
117
+
88
118
  When you run the test suite now, it will use the updated fixture files.
89
119
 
90
120
  ## Disclaimer
data/gares.gemspec CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
22
22
  s.add_dependency 'nokogiri', '~> 1.6'
23
23
  s.add_dependency 'hashie', '~> 3.4'
24
24
  s.add_dependency 'unidecoder', '~> 1.1'
25
+ s.add_dependency 'httparty', '~> 0.13'
25
26
 
26
27
  s.add_development_dependency 'rake'
27
28
  s.add_development_dependency 'rspec'
@@ -0,0 +1,62 @@
1
+ require "net/http"
2
+ require "uri"
3
+
4
+ module Gares
5
+ # Represents something a train from http://www.sncf.com/fr/horaires-info-trafic/train
6
+ class Train
7
+ attr_accessor :date, :number
8
+
9
+ # Initialize a new Train object with it's number and departure date
10
+ #
11
+ # train = Gares::Train.new(6704, Time.parse('2015-04-15'))
12
+ #
13
+ # Gares::Train objects are lazy loaded, meaning that no HTTP request
14
+ # will be performed when a new object is created. An HTTP request is made (once)
15
+ # Only when you use an accessor that needs the remote data.
16
+ def initialize(number, date)
17
+ fail "Please provide a train number" unless number.is_a?(Integer)
18
+ fail "Please provide a departure date" unless date.is_a?(Time)
19
+
20
+ @number = number
21
+ @date = date
22
+ end
23
+
24
+ # @return [TrainStop] The departure point of the train
25
+ def departure
26
+ @departure ||= TrainStop.new(document.at('tr.itinerary-start'), @date)
27
+ end
28
+
29
+ # @return [Array<TrainStop>] A list of all stops between departure and arrival stations.
30
+ def stops
31
+ @stops ||= document.css('tr.itinerary-stop').map { |stop| TrainStop.new(stop, @date) }
32
+ end
33
+
34
+ # @return [TrainStop] The arrival point of the train
35
+ def arrival
36
+ @arrival ||= TrainStop.new(document.at('tr.itinerary-end'), @date)
37
+ end
38
+
39
+ def delayed?
40
+ ([departure] + stops + [arrival]).any?(&:delayed?)
41
+ end
42
+
43
+ private
44
+
45
+ # Returns a new Nokogiri document for parsing.
46
+ def document
47
+ @document ||= Nokogiri::HTML(self.class.request_sncf(@number, @date))
48
+ end
49
+
50
+ def self.request_sncf(number, date)
51
+ uri = URI.parse("http://www.sncf.com/sncf/train")
52
+ response = Net::HTTP.post_form(uri, {"numeroTrain" => number, "date" => date.strftime("%d/%m/%Y")})
53
+ cookies = response.get_fields('Set-Cookie').map { |cookie| cookie.split(";").first }.join(";")
54
+
55
+ uri = URI.parse("http://www.sncf.com/en/horaires-info-trafic/train/resultats")
56
+ req = Net::HTTP::Get.new(uri.path)
57
+ req.add_field("Cookie", cookies)
58
+ Net::HTTP.new(uri.host, uri.port).start { |http| http.request(req) }.body
59
+ end
60
+
61
+ end # Train
62
+ end # Gares
@@ -0,0 +1,86 @@
1
+ require 'time'
2
+
3
+ module Gares
4
+ # Represents a stop for a train from http://www.sncf.com/fr/horaires-info-trafic/train
5
+ class TrainStop
6
+ # @!attribute departure_date
7
+ # @return [Time] The scheduled departure date at this stop.
8
+
9
+ # @!attribute real_departure_date
10
+ # @return [Time] The live schedule departure date at this stop.
11
+
12
+ # @!attribute arrival_date
13
+ # @return [Time] The scheduled arrival date at this stop.
14
+
15
+ # @!attribute real_arrival_date
16
+ # @return [Time] The live schedule departure date at this stop.
17
+
18
+ # @!attribute station
19
+ # @return [Station] The station in which this train is stopping.
20
+
21
+ # @!attribute platform
22
+ # @return [String] The platform number/letter if available.
23
+
24
+ # @!attribute formatted_info
25
+ # @return [String] A formatted detailed information in HTML.
26
+
27
+ attr_accessor :departure_date, :real_departure_date, :arrival_date, :real_arrival_date,
28
+ :station, :platform, :formatted_info
29
+
30
+ # Given the HTML node from sncf.com/fr/horaires-info-trafic/train containing the stop
31
+ # and the +date+ for this train stop.
32
+ # The object gathers all useful information about the stop made by the train.
33
+ def initialize(nokogiri_node, date)
34
+ initialize_dates(nokogiri_node, date)
35
+ initialize_station(nokogiri_node)
36
+ @platform = nokogiri_node.at('td.track').inner_html.strip
37
+ @formatted_info = nokogiri_node.at('td.info').inner_html.strip
38
+ end
39
+
40
+ def delayed?
41
+ minutes_of_delay > 0
42
+ end
43
+
44
+ # @return [Integer] The amount of minutes of delay at this stop.
45
+ def minutes_of_delay
46
+ if @real_departure_date
47
+ (@real_departure_date - @departure_date) / 60
48
+ else
49
+ 0
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ def initialize_dates(node, date)
56
+ raw_time = node.at('td.time').inner_html.strip
57
+ raw_real_time = node.at('td.new-schedule').inner_html.strip
58
+ raw_arrival_time = raw_time.split('<br/>').first
59
+ raw_departure_time = raw_time.split('<br/>').last
60
+ raw_real_arrival_time = raw_real_time.split('<br/>').first
61
+ raw_real_departure_time = raw_real_time.split('<br/>').last
62
+
63
+ @departure_date = Time.parse(raw_departure_time, date)
64
+ @arrival_date = Time.parse(raw_arrival_time, date)
65
+ if raw_real_departure_time
66
+ @real_departure_date = Time.parse(raw_real_departure_time, date)
67
+ end
68
+ if raw_real_arrival_time
69
+ @real_arrival_date = Time.parse(raw_real_arrival_time, date)
70
+ end
71
+ end
72
+
73
+ def initialize_station(node)
74
+ raw_name = node.at('td.stations div.station').inner_html.strip
75
+ stations = Station.search(raw_name)
76
+ @station = if stations.size > 1
77
+ stations.find do |station|
78
+ name = /(^#{raw_name}$|^#{raw_name} | #{raw_name}$| #{raw_name} )/i
79
+ station.name.match(name)
80
+ end
81
+ else
82
+ stations.first
83
+ end
84
+ end
85
+ end
86
+ end
data/lib/gares/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Gares
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end
data/lib/gares.rb CHANGED
@@ -7,6 +7,7 @@ require 'nokogiri'
7
7
  require 'json'
8
8
  require 'hashie'
9
9
  require 'unidecoder'
10
+ require 'httparty'
10
11
 
11
12
  require 'gares/base'
12
13
  require 'gares/station'
@@ -15,4 +16,6 @@ require 'gares/sales'
15
16
  require 'gares/services'
16
17
  require 'gares/search'
17
18
  require 'gares/string_extensions'
19
+ require 'gares/train'
20
+ require 'gares/train_stop'
18
21
  require 'gares/version'