gares 2.0.0.pre.pre → 2.0.0.pre.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f87e7dc8b8d185548c8dcc4c12c789e07802caea
4
- data.tar.gz: 971aa5a58e033f79d41f901899bc6d862c56f5f0
3
+ metadata.gz: a3462299801d297e26ac19012e511cb92b71257b
4
+ data.tar.gz: 2402a19990a9bf1f1e1b8334b24126a08c368439
5
5
  SHA512:
6
- metadata.gz: 4432ec3fa4011d82f5b22f63aa647e7b75fca52fa2222335032f9cbb0b5078bcb59008d9d9bfd4fe9474143248d212beac197c2c5758b871519968bed5a8fd38
7
- data.tar.gz: 9afd2bd055b35a12e10b15b10d9a29c4208744c0ae1a119c39403f4b8ccfb9ad06c66e1f6d92c8b6bdd09113e6d9c9a068ee9b41412cbad0586127a4ced2f589
6
+ metadata.gz: 79d40ec3a9d068bd76716cf73e1de3c45f4ea439663fbfeb2cee2588ca8c4fc428652db6f52ed4532d91bfbbbf5cbbd85ba888b848d91d0e6001539f2817cee1
7
+ data.tar.gz: dbfd7ea33abbb67f5334f81834ef8d9d652d9ef232acf3e36ce94bd6feed2265b69860cf26a7b6f8a9bf1babba29d3e5344c5c1ad8d683e2f2b7033d6239a664
data/gares.gemspec CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
24
24
  s.add_dependency 'smarter_csv', '~> 1.0'
25
25
  s.add_dependency 'unidecoder', '~> 1.1'
26
26
  s.add_dependency 'httparty', '~> 0.13'
27
+ s.add_dependency 'trie'
27
28
 
28
29
  s.add_development_dependency 'rake'
29
30
  s.add_development_dependency 'rspec'
@@ -0,0 +1,47 @@
1
+ # Fork of https://raw.githubusercontent.com/rails/rails/master/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
2
+ class Module
3
+ def mattr_reader(*syms)
4
+ syms.each do |sym|
5
+ raise NameError.new("invalid attribute name: #{sym}") unless sym =~ /^[_A-Za-z]\w*$/
6
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
7
+ @@#{sym} = nil unless defined? @@#{sym}
8
+
9
+ def self.#{sym}
10
+ @@#{sym}
11
+ end
12
+ EOS
13
+
14
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
15
+ def #{sym}
16
+ @@#{sym}
17
+ end
18
+ EOS
19
+ class_variable_set("@@#{sym}", yield) if block_given?
20
+ end
21
+ end
22
+
23
+ def mattr_writer(*syms)
24
+ syms.each do |sym|
25
+ raise NameError.new("invalid attribute name: #{sym}") unless sym =~ /^[_A-Za-z]\w*$/
26
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
27
+ @@#{sym} = nil unless defined? @@#{sym}
28
+
29
+ def self.#{sym}=(obj)
30
+ @@#{sym} = obj
31
+ end
32
+ EOS
33
+
34
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
35
+ def #{sym}=(obj)
36
+ @@#{sym} = obj
37
+ end
38
+ EOS
39
+ send("#{sym}=", yield) if block_given?
40
+ end
41
+ end
42
+
43
+ def mattr_accessor(*syms, &blk)
44
+ mattr_reader(*syms, &blk)
45
+ mattr_writer(*syms, &blk)
46
+ end
47
+ end
data/lib/gares/search.rb CHANGED
@@ -1,13 +1,16 @@
1
+ require 'trie'
2
+
1
3
  module Gares
2
4
  # Search Gares-en-mouvement for a station name
3
5
  class Search < StationList
6
+ @@trie = nil
7
+ mattr_reader :trie
8
+
4
9
  attr_reader :query
5
10
 
6
11
  # This is the stations database from capitainetrain.com
7
12
  GARES_LIST_URL = "https://raw.githubusercontent.com/capitainetrain/stations/master/stations.csv"
8
13
 
9
- # List of keywords to ignore while searching
10
- IGNORE_KEYWORDS = ["ST", "SAINT", "GARE", "SNCF"]
11
14
  # Initialize a new Station search with the specified query
12
15
  #
13
16
  # search = Gares::Search.new("Aix")
@@ -29,41 +32,46 @@ module Gares
29
32
  @stations ||= (exact_match? ? parse_station : parse_stations)
30
33
  end
31
34
 
35
+ def self.find(str)
36
+ trie.find_prefix(str)
37
+ end
38
+
32
39
  private
33
40
 
34
41
  def result
35
- @raw_result ||= case @by
36
- when :name
37
- keywords = @query.to_ascii.split(/[ -]/).select { |keyword| !IGNORE_KEYWORDS.include?(keyword.upcase) }
38
- regexp_query = keywords.join(".*")
39
- self.class.data(@by).select do |index, v|
40
- index && index =~ /#{regexp_query}/i
41
- end
42
- when :sncf_id
43
- { @query.downcase => self.class.data(@by)[@query.downcase] }
42
+ query = self.class.simplify(@query)
43
+ if @raw_results.nil?
44
+ @raw_results = self.class.find(query).values
45
+ # try first keyword if nothing found
46
+ @raw_results = @raw_results.empty? ? self.class.find(query.split(" ").first).values : @raw_results
44
47
  end
45
-
46
- @result ||= @raw_result.map { |_, raw_station| Gares::Station.new(raw_station) }
48
+ @result ||= @raw_results.map { |raw_station| Gares::Station.new(raw_station) }
47
49
  end
48
50
 
49
- # Read stations.csv file into memory
50
- # @param index either :name or :sncf_id
51
- # @return [Hash<String, Hash>] list of stations indexed in a Hash
52
- def self.data(index)
53
- @@raw_data ||= SmarterCSV.process(open(GARES_LIST_URL), col_sep: ";")
54
- case index
55
- when :name
56
- @@data_by_name ||= index_data(@@raw_data, index)
57
- when :sncf_id
58
- @@data_by_sncf_id ||= index_data(@@raw_data, index)
59
- end
51
+ def self.simplify(str)
52
+ str.to_ascii.downcase
53
+ .gsub(/\bsaint\b/, "st")
54
+ .gsub(/[^a-z]/, " ")
55
+ .gsub(/\s+/, " ")
56
+ .strip
60
57
  end
61
58
 
62
- def self.index_data(data, by)
63
- data.map do |raw_station|
64
- [raw_station[by].to_ascii.downcase, raw_station] if raw_station[by] && raw_station[:uic]
65
- end.compact.to_h
59
+ # Read stations.csv file into memory into a Trie data structure
60
+ def self.load_data
61
+ if @@trie.nil?
62
+ raw_data ||= SmarterCSV.process(open(GARES_LIST_URL), col_sep: ";")
63
+ trie = Trie.new
64
+
65
+ raw_data.each do |raw_station|
66
+ next if raw_station[:name].nil? || raw_station[:sncf_id].nil? || raw_station[:uic].nil?
67
+ trie.insert(simplify(raw_station[:name]), raw_station)
68
+ trie.insert(simplify(raw_station[:sncf_id]), raw_station)
69
+ end
70
+
71
+ @@trie = trie
72
+ end
66
73
  end
74
+ load_data
67
75
 
68
76
  def parse_station
69
77
  [result.first]
data/lib/gares/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Gares
2
- VERSION = '2.0.0-pre'
2
+ VERSION = '2.0.0-1'
3
3
  end
data/lib/gares.rb CHANGED
@@ -9,6 +9,8 @@ require 'hashie'
9
9
  require 'smarter_csv'
10
10
  require 'unidecoder'
11
11
  require 'httparty'
12
+ require 'attribute_accessors'
13
+ require 'string_extensions'
12
14
 
13
15
  require 'gares/errors'
14
16
  require 'gares/base'
@@ -17,7 +19,6 @@ require 'gares/station_list'
17
19
  require 'gares/sales'
18
20
  require 'gares/services'
19
21
  require 'gares/search'
20
- require 'gares/string_extensions'
21
22
  require 'gares/train'
22
23
  require 'gares/train_stop'
23
24
  require 'gares/version'
@@ -0,0 +1,20 @@
1
+ require 'cgi'
2
+
3
+ module StringExtensions
4
+ # Unescape HTML
5
+ def unescape_html
6
+ CGI.unescapeHTML(encode('UTF-8'))
7
+ end
8
+
9
+ # Strip tags
10
+ def strip_tags
11
+ gsub(/<\/?[^>]*>/, '')
12
+ end
13
+
14
+ # Strips out whitespace then tests if the string is empty.
15
+ def blank?
16
+ strip.empty?
17
+ end unless method_defined?(:blank?)
18
+ end
19
+
20
+ String.send :include, StringExtensions
@@ -4,15 +4,15 @@ describe Gares::Search do
4
4
  describe "search by station name" do
5
5
  context 'with multiple search results' do
6
6
  subject do
7
- Gares::Search.new('étienne')
7
+ Gares::Search.new('saint étienne')
8
8
  end
9
9
 
10
10
  it 'should remember the query' do
11
- expect(subject.query).to eql('étienne')
11
+ expect(subject.query).to eql('saint étienne')
12
12
  end
13
13
 
14
- it 'should find 28 results' do
15
- expect(subject.stations.size).to eql(12)
14
+ it 'should find 11 results' do
15
+ expect(subject.stations.size).to eql(11)
16
16
  end
17
17
 
18
18
  it 'should return Gares::Station objects only' do
@@ -32,7 +32,7 @@ describe Gares::Search do
32
32
  subject { Gares::Station.search('Saone').first }
33
33
 
34
34
  it 'should give the proper name' do
35
- expect(subject.name).to eql('Port-sur-Saône')
35
+ expect(subject.name).to eql('Saône')
36
36
  end
37
37
  end
38
38
 
@@ -82,7 +82,7 @@ describe Gares::Search do
82
82
 
83
83
  it 'should return the gare sncf_id.downcase correctly' do
84
84
  subject = Gares::Station.search('MONTELIMAR GARE SNCF')
85
- expect(subject.first.sncf_id.downcase).to eql('frxmk')
85
+ expect(subject.first.sncf_id.downcase).to eql('frmtl')
86
86
  end
87
87
 
88
88
  it 'should return the gare sncf_id.downcase correctly' do
@@ -98,7 +98,7 @@ describe Gares::Train do
98
98
  expect(subject.departure.delayed?).to be(false)
99
99
  end
100
100
 
101
- it "has stops", focus: true do
101
+ it "has stops" do
102
102
  expect(subject.stops.size).to eq(7)
103
103
  expect(subject.stops.first.station.name).to eq('Nogent-sur-Seine')
104
104
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gares
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre.pre
4
+ version: 2.0.0.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Bonaud
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-01 00:00:00.000000000 Z
11
+ date: 2015-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0.13'
83
+ - !ruby/object:Gem::Dependency
84
+ name: trie
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: rake
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -210,6 +224,7 @@ files:
210
224
  - README.md
211
225
  - Rakefile
212
226
  - gares.gemspec
227
+ - lib/attribute_accessors.rb
213
228
  - lib/gares.rb
214
229
  - lib/gares/base.rb
215
230
  - lib/gares/errors.rb
@@ -218,10 +233,10 @@ files:
218
233
  - lib/gares/services.rb
219
234
  - lib/gares/station.rb
220
235
  - lib/gares/station_list.rb
221
- - lib/gares/string_extensions.rb
222
236
  - lib/gares/train.rb
223
237
  - lib/gares/train_stop.rb
224
238
  - lib/gares/version.rb
239
+ - lib/string_extensions.rb
225
240
  - spec/fixtures/frabt
226
241
  - spec/fixtures/frabt-services-vente
227
242
  - spec/fixtures/frhco
@@ -1,22 +0,0 @@
1
- require 'cgi'
2
-
3
- module Gares #:nordoc:
4
- module StringExtensions
5
- # Unescape HTML
6
- def unescape_html
7
- CGI.unescapeHTML(encode('UTF-8'))
8
- end
9
-
10
- # Strip tags
11
- def strip_tags
12
- gsub(/<\/?[^>]*>/, '')
13
- end
14
-
15
- # Strips out whitespace then tests if the string is empty.
16
- def blank?
17
- strip.empty?
18
- end unless method_defined?(:blank?)
19
- end
20
- end
21
-
22
- String.send :include, Gares::StringExtensions