ekispert 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.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +48 -0
  3. data/.gitignore +14 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +110 -0
  6. data/.travis.yml +5 -0
  7. data/CODE_OF_CONDUCT.md +74 -0
  8. data/Gemfile +6 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +118 -0
  11. data/Rakefile +6 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/ekispert-sdk-ruby.gemspec +31 -0
  15. data/example/point_station.rb +20 -0
  16. data/example/search_course.rb +116 -0
  17. data/lib/ekispert.rb +43 -0
  18. data/lib/ekispert/client.rb +58 -0
  19. data/lib/ekispert/config.rb +30 -0
  20. data/lib/ekispert/course.rb +124 -0
  21. data/lib/ekispert/course/pass_status.rb +34 -0
  22. data/lib/ekispert/course/price.rb +71 -0
  23. data/lib/ekispert/course/route.rb +33 -0
  24. data/lib/ekispert/course/route/line.rb +86 -0
  25. data/lib/ekispert/course/route/line/arrival_state.rb +25 -0
  26. data/lib/ekispert/course/route/line/arrival_state/gate.rb +22 -0
  27. data/lib/ekispert/course/route/line/corporation.rb +22 -0
  28. data/lib/ekispert/course/route/line/departure_state.rb +25 -0
  29. data/lib/ekispert/course/route/line/departure_state/gate.rb +22 -0
  30. data/lib/ekispert/course/route/line/line_symbol.rb +22 -0
  31. data/lib/ekispert/course/route/line/stop.rb +30 -0
  32. data/lib/ekispert/course/route/line/stop/arrival_state.rb +28 -0
  33. data/lib/ekispert/course/route/line/stop/departure_state.rb +28 -0
  34. data/lib/ekispert/course/route/line/stop/point.rb +28 -0
  35. data/lib/ekispert/course/route/line/stop/point/prefecture.rb +26 -0
  36. data/lib/ekispert/course/route/line/stop/point/station.rb +30 -0
  37. data/lib/ekispert/course/route/point.rb +49 -0
  38. data/lib/ekispert/course/route/point/prefecture.rb +22 -0
  39. data/lib/ekispert/course/route/point/station.rb +34 -0
  40. data/lib/ekispert/data_version.rb +35 -0
  41. data/lib/ekispert/ekispert_base.rb +69 -0
  42. data/lib/ekispert/error.rb +29 -0
  43. data/lib/ekispert/information.rb +58 -0
  44. data/lib/ekispert/information/corporation.rb +20 -0
  45. data/lib/ekispert/information/exit.rb +24 -0
  46. data/lib/ekispert/information/line.rb +35 -0
  47. data/lib/ekispert/information/welfare_facilities.rb +24 -0
  48. data/lib/ekispert/point.rb +41 -0
  49. data/lib/ekispert/point/prefecture.rb +18 -0
  50. data/lib/ekispert/point/station.rb +65 -0
  51. data/lib/ekispert/point/station/gate_group.rb +14 -0
  52. data/lib/ekispert/point/station/gate_group/gate.rb +28 -0
  53. data/lib/ekispert/util.rb +11 -0
  54. data/lib/ekispert/version.rb +3 -0
  55. metadata +213 -0
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,31 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'ekispert/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'ekispert'
7
+ spec.version = Ekispert::VERSION
8
+ spec.authors = ['Ekispert Web Service']
9
+
10
+ spec.summary = 'Ekispert API Client'
11
+ spec.description = 'wrapper for the Ekispert API'
12
+ spec.homepage = 'https://github.com/EkispertWebService/ekispert-sdk-ruby/'
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
+ f.match(%r{^(test|spec|features)/})
17
+ end
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'faraday', ['>= 0.7.4', '< 1.0']
23
+ spec.add_dependency 'faraday_middleware', '~> 0.12.2'
24
+ spec.add_dependency 'nokogiri', '~> 1.8.2'
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.16'
27
+ spec.add_development_dependency 'pry-byebug'
28
+ spec.add_development_dependency 'rake', '~> 10.0'
29
+ spec.add_development_dependency 'rspec', '~> 3.0'
30
+ spec.add_development_dependency 'rubocop', '~> 0.59.0'
31
+ end
@@ -0,0 +1,20 @@
1
+ require 'ekispert'
2
+
3
+ station_list = Ekispert::Point::Station.get(code:'22828', addGateGroup: true)
4
+ station = station_list[0]
5
+ puts "Station: #{station.name}"
6
+ puts "Latitude: #{station.geo_point.lati_d}"
7
+ puts "Longitude: #{station.geo_point.longi_d}"
8
+ station.gate_group_list.each do |gate_group|
9
+ gate_group.gate_list.each do |gate|
10
+ puts "Gate: #{gate.name}"
11
+ end
12
+ end
13
+
14
+ # Station: 東京
15
+ # Latitude: 35.678083
16
+ # Longitude: 139.770444
17
+ # Gate: 京葉線1(北側)
18
+ # Gate: 京葉線1(南側)
19
+ # Gate: 京葉線2
20
+ # ... and more
@@ -0,0 +1,116 @@
1
+ require 'ekispert'
2
+
3
+ # Train Station
4
+ course_list = Ekispert::Course.get(viaList: '22828:22741', answerCount: 2, addStop: true)
5
+
6
+ # Local Bus
7
+ # course_list = Ekispert::Course.get(viaList: '51003:51487', answerCount: 2, addStop: true)
8
+
9
+ course_list.each.with_index(1) do |course, i|
10
+ price_list = course.price_list
11
+ route = course.route
12
+ point_list = route.point_list
13
+ line_list = route.line_list
14
+
15
+ puts "======= Summary #{i} ======="
16
+ puts "合計所要時間: #{route.total_required_time}分"
17
+ puts "乗り換え回数: #{route.transfer_count}回"
18
+ puts "合計金額: #{course.oneway_price}円"
19
+ puts "出発時刻: #{route.departure_time.strftime("%H:%M")}"
20
+ puts "到着時刻: #{route.arrival_time.strftime("%H:%M")}"
21
+ puts "--- 定期代 ---"
22
+ puts "1ヶ月: #{course.teiki1.oneway}円"
23
+ puts "3ヶ月: #{course.teiki3.oneway}円"
24
+ puts "6ヶ月: #{course.teiki6.oneway}円"
25
+ puts "========================="
26
+
27
+ line_list.each_with_index do |line, j|
28
+ puts "#{line.departure_state.datetime.strftime('%H:%M')} #{point_list[j].station.name}"
29
+ if line.line_symbol
30
+ puts " | [#{line.line_symbol.name}] #{line.name} #{line.fare.oneway}円"
31
+ else
32
+ puts " | #{line.name}"
33
+ end
34
+ end
35
+ puts "#{line_list[-1].arrival_state.datetime.strftime('%H:%M')} #{point_list[-1].station.name}"
36
+ print "\n"
37
+
38
+ puts "--- 停車駅一覧 ---"
39
+
40
+ line_list.each_with_index do |line, s|
41
+ next if ['walk', 'strange'].include?(line.type)
42
+ puts "■ #{line.name}\n"
43
+ line.stop_list[0...-1].each do |stop|
44
+ puts "#{stop.departure_state.datetime.strftime('%H:%M')} #{stop.point.station.name}"
45
+ puts " |"
46
+ end
47
+ puts "#{line.stop_list[-1].departure_state.datetime.strftime('%H:%M')} #{line.stop_list[-1].point.station.name}"
48
+ print "\n"
49
+ end
50
+ end
51
+
52
+ # ======= Summary 1 =======
53
+ # 合計所要時間: 14分
54
+ # 乗り換え回数: 0回
55
+ # 合計金額: 200円
56
+ # 出発時刻: 12:00
57
+ # 到着時刻: 12:14
58
+ # --- 定期代 ---
59
+ # 1ヶ月: 5820円
60
+ # 3ヶ月: 16580円
61
+ # 6ヶ月: 27920円
62
+ # =========================
63
+ # 12:00 東京
64
+ # | [JC] JR中央・青梅線快速・青梅行 200円
65
+ # 12:14 新宿
66
+ #
67
+ # --- 停車駅一覧 ---
68
+ # ■ JR中央・青梅線快速・青梅行
69
+ # 12:00 東京
70
+ # |
71
+ # 12:02 神田(東京都)
72
+ # |
73
+ # 12:04 御茶ノ水
74
+ # |
75
+ # 12:09 四ツ谷
76
+ # |
77
+ # 12:14 新宿
78
+ #
79
+ # ======= Summary 2 =======
80
+ # 合計所要時間: 22分
81
+ # 乗り換え回数: 0回
82
+ # 合計金額: 200円
83
+ # 出発時刻: 12:09
84
+ # 到着時刻: 12:31
85
+ # --- 定期代 ---
86
+ # 1ヶ月: 7320円
87
+ # 3ヶ月: 20870円
88
+ # 6ヶ月: 39530円
89
+ # =========================
90
+ # 12:00 東京
91
+ # | [M] 東京メトロ丸ノ内線・荻窪行 200円
92
+ # 12:20 新宿(東京メトロ)
93
+ # | 徒歩
94
+ # 12:22 新宿
95
+ #
96
+ # --- 停車駅一覧 ---
97
+ # ■ 東京メトロ丸ノ内線・荻窪行
98
+ # 12:00 東京
99
+ # |
100
+ # 12:02 銀座
101
+ # |
102
+ # 12:04 霞ケ関(東京都)
103
+ # |
104
+ # 12:06 国会議事堂前
105
+ # |
106
+ # 12:09 赤坂見附
107
+ # |
108
+ # 12:11 四ツ谷
109
+ # |
110
+ # 12:14 四谷三丁目
111
+ # |
112
+ # 12:15 新宿御苑前
113
+ # |
114
+ # 12:17 新宿三丁目
115
+ # |
116
+ # 12:20 新宿(東京メトロ)
data/lib/ekispert.rb ADDED
@@ -0,0 +1,43 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+ require 'nokogiri'
4
+ require 'yaml'
5
+ require 'date'
6
+
7
+ require 'ekispert/util'
8
+ require 'ekispert/ekispert_base'
9
+ require 'ekispert/version'
10
+ require 'ekispert/config'
11
+ require 'ekispert/client'
12
+ require 'ekispert/data_version'
13
+ require 'ekispert/information'
14
+ require 'ekispert/information/line'
15
+ require 'ekispert/information/corporation'
16
+ require 'ekispert/information/exit'
17
+ require 'ekispert/information/welfare_facilities'
18
+ require 'ekispert/error'
19
+ require 'ekispert/point'
20
+ require 'ekispert/point/station'
21
+ require 'ekispert/point/station/gate_group'
22
+ require 'ekispert/point/station/gate_group/gate'
23
+ require 'ekispert/point/prefecture'
24
+ require 'ekispert/course'
25
+ require 'ekispert/course/route'
26
+ require 'ekispert/course/route/line'
27
+ require 'ekispert/course/route/line/arrival_state'
28
+ require 'ekispert/course/route/line/arrival_state/gate'
29
+ require 'ekispert/course/route/line/departure_state'
30
+ require 'ekispert/course/route/line/departure_state/gate'
31
+ require 'ekispert/course/route/line/corporation'
32
+ require 'ekispert/course/route/line/line_symbol'
33
+ require 'ekispert/course/route/line/stop'
34
+ require 'ekispert/course/route/line/stop/arrival_state'
35
+ require 'ekispert/course/route/line/stop/departure_state'
36
+ require 'ekispert/course/route/line/stop/point'
37
+ require 'ekispert/course/route/line/stop/point/prefecture'
38
+ require 'ekispert/course/route/line/stop/point/station'
39
+ require 'ekispert/course/route/point'
40
+ require 'ekispert/course/route/point/station'
41
+ require 'ekispert/course/route/point/prefecture'
42
+ require 'ekispert/course/price'
43
+ require 'ekispert/course/pass_status'
@@ -0,0 +1,58 @@
1
+ module Ekispert
2
+ class Client
3
+ def self.get(path, params=nil)
4
+ set_connection if @connection.nil? || connection_options_update?
5
+ res = @connection.get(path, params)
6
+ return parse_xml(res.body) if res.status == 200
7
+
8
+ raise_error(res)
9
+ end
10
+
11
+ def self.connection_options
12
+ {
13
+ url: "#{Config.host}/#{Config.version}/xml",
14
+ proxy: Config.http_proxy,
15
+ headers: { 'Content-Type' => 'application/xml;charset=utf-8' },
16
+ params: { key: Ekispert::Config.api_key },
17
+ request: { timeout: 5, open_timeout: 2 }
18
+ }
19
+ end
20
+
21
+ def self.set_connection
22
+ @connection_options = connection_options
23
+ @connection = Faraday.new(@connection_options) do |c|
24
+ c.adapter Faraday.default_adapter
25
+ end
26
+ end
27
+
28
+ # Below are private class methods
29
+
30
+ def self.connection_options_update?
31
+ @connection_options != connection_options
32
+ end
33
+
34
+ def self.parse_xml(xml)
35
+ Nokogiri::XML.parse(xml).xpath('//ResultSet')
36
+ end
37
+
38
+ def self.raise_error(res)
39
+ case res.status
40
+ when 1
41
+ raise Error::InternalError, 'Engine Error'
42
+ when 400
43
+ raise Error::BadRequest, res
44
+ when 403
45
+ raise Error::Forbidden, res
46
+ when 404
47
+ raise Error::NotFound, res
48
+ when 400..499
49
+ raise Error::ClientError, res
50
+ when 500..599
51
+ raise Error::ServerError, 'OMG!'
52
+ end
53
+ end
54
+
55
+ private_class_method :connection_options_update?
56
+ private_class_method :parse_xml, :raise_error
57
+ end
58
+ end
@@ -0,0 +1,30 @@
1
+ module Ekispert
2
+ class Config
3
+ DEFAULTS = {
4
+ host: 'https://api.ekispert.jp',
5
+ version: 'v1',
6
+ http_proxy: ENV['HTTP_PROXY'],
7
+ api_key: ENV['EKISPERT_API_KEY']
8
+ }.freeze
9
+ DEFAULTS.each do |option, value|
10
+ class_eval <<-EOS, __FILE__, __LINE__ + 1
11
+ class << self
12
+ attr_accessor :#{option}
13
+ end
14
+ EOS
15
+ instance_variable_set("@#{option}", value)
16
+ end
17
+
18
+ def self.list
19
+ options = {}
20
+ self.instance_variables.each do |name|
21
+ options[name] = instance_variable_get(name)
22
+ end
23
+ options
24
+ end
25
+
26
+ def self.set
27
+ yield self
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,124 @@
1
+ module Ekispert
2
+ class Course < EkispertBase
3
+ attr_accessor :route_list, :price_list, :pass_status_list, :serialize_data_list
4
+ attr_accessor :fare, :charge, :teiki1, :teiki3, :teiki6, :teiki12
5
+
6
+ def initialize(element)
7
+ @route_list = []
8
+ @price_list = []
9
+ @pass_status_list = []
10
+ @serialize_data_list = []
11
+ super(element)
12
+ define_summary_method
13
+ relate_line_to_price
14
+ relate_price_to_line
15
+ relate_price_and_pass_status
16
+ end
17
+
18
+ def route
19
+ @route_list[0]
20
+ end
21
+
22
+ def serialize_data
23
+ @serialize_data_list[0].text
24
+ end
25
+
26
+ def oneway_price
27
+ fare.oneway + charge.oneway
28
+ end
29
+
30
+ def round_price
31
+ fare.round + charge.round
32
+ end
33
+
34
+ def self.get(params={})
35
+ to_course(Ekispert::Client.get('search/course/extreme', params))
36
+ end
37
+
38
+ def self.to_course(elem_arr)
39
+ elem_arr.xpath('//Course').map { |course_elem| self.new(course_elem) }
40
+ end
41
+
42
+ class SerializeData < EkispertBase; end
43
+
44
+ private_class_method :to_course
45
+
46
+ private
47
+
48
+ # This method define summary methods.
49
+ # If nothing 'HogeSummary' elements, create and set empty Course::Price instance.
50
+ # result:
51
+ # Course#fare
52
+ # Course#charge
53
+ # Course#teiki1 ...
54
+ def define_summary_method
55
+ %w[fare charge teiki1 teiki3 teiki6 teiki12].each do |summary_type|
56
+ self.define_singleton_method(summary_type) { price_summary(summary_type) }
57
+ end
58
+ end
59
+
60
+ def price_summary(type)
61
+ @price_list.find { |price| price.kind == "#{type.capitalize}Summary" } || Ekispert::Course::Price.new
62
+ end
63
+
64
+ # This method relate Course::Route::Line instance to Course::Price instance.
65
+ # If even without those associated with Line, return Price instance.
66
+ # Ex.
67
+ # Course::Route::Line#fare
68
+ # Course::Route::Line#charge
69
+ # Course::Route::Line#teiki1 etc...
70
+ def relate_line_to_price
71
+ @route_list[0].line_list.each do |line|
72
+ line.fare = find_price(line, :fare)
73
+ line.charge = find_price(line, :charge)
74
+ line.teiki1 = find_price(line, :teiki1)
75
+ line.teiki3 = find_price(line, :teiki3)
76
+ line.teiki6 = find_price(line, :teiki6)
77
+ line.teiki12 = find_price(line, :teiki12)
78
+ end
79
+ end
80
+
81
+ def find_price(line, price_type)
82
+ index_type = "#{price_type}_index"
83
+ return Ekispert::Course::Price.new unless line.respond_to?(index_type)
84
+
85
+ kind = price_type.to_s.capitalize
86
+ @price_list.find { |price| price.kind == kind && price.index == line.send(index_type) }
87
+ end
88
+
89
+ # This method relate Course::Price instance to Course::Route::Line instance.
90
+ # It's judged based on to Price#from_line_index and Price#from_line_index.
91
+ # result:
92
+ # Course::Price#line_list
93
+ def relate_price_to_line
94
+ @price_list.each do |price|
95
+ next unless price.respond_to?(:from_line_index)
96
+
97
+ price_range = (price.from_line_index.to_i..price.to_line_index.to_i)
98
+ price.line_list = @route_list[0].line_list.select { |line| price_range.include?(line.index.to_i) }
99
+ end
100
+ end
101
+
102
+ # This method relate Course::Price instance and Course::PassStatus instance.
103
+ # It's judged based on to Price#pass_class_index.
104
+ # result:
105
+ # Course::Price#pass_status
106
+ def relate_price_and_pass_status
107
+ price_list.each do |price|
108
+ next unless price.kind.match?(/^Teiki\d{1}$/)
109
+
110
+ pass_status = find_pass_status(price)
111
+ # Price to PassStatus
112
+ price.pass_status = pass_status
113
+ # PassStatus to Price
114
+ pass_status.price_list << price
115
+ end
116
+ end
117
+
118
+ def find_pass_status(price)
119
+ return Ekispert::Course::PassStatus.new unless price.respond_to?(:pass_class_index)
120
+
121
+ @pass_status_list.find { |status| status.index == price.pass_class_index }
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,34 @@
1
+ module Ekispert
2
+ class Course < EkispertBase
3
+ class PassStatus < EkispertBase
4
+ attr_accessor :comment_list, :name_list, :type_list
5
+ attr_accessor :price_list
6
+
7
+ def initialize(element=nil)
8
+ @comment_list = []
9
+ @name_list = []
10
+ @type_list = []
11
+ @price_list = [] # Use Course#relate_price_and_pass_status
12
+ return if element.nil?
13
+
14
+ super(element)
15
+ end
16
+
17
+ def comment
18
+ @comment_list[0]&.text
19
+ end
20
+
21
+ def name
22
+ @name_list[0]&.text
23
+ end
24
+
25
+ def type
26
+ @type_list[0]&.text
27
+ end
28
+
29
+ class Comment < EkispertBase; end
30
+ class Name < EkispertBase; end
31
+ class Type < EkispertBase; end
32
+ end
33
+ end
34
+ end