em-synchrony-dataone-vin 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 +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +8 -0
- data/em-synchrony-dataone-vin.gemspec +26 -0
- data/lib/em-synchrony/dataone-vin/version.rb +7 -0
- data/lib/em-synchrony/dataone-vin/vin_exploder_adapter.rb +165 -0
- data/lib/em-synchrony/dataone-vin.rb +92 -0
- data/test/em-synchrony/dataone-vin/vin_exploder_adapter_test.rb +52 -0
- data/test/em-synchrony/dataone-vin_test.rb +23 -0
- data/test/test_helper.rb +639 -0
- data/test.rb +177 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c877baafea2c7245911ad6694c98d8a623c0fa64
|
4
|
+
data.tar.gz: 3a99bf467ca37e2d9779c867708514ad75af8f42
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c74f30d047628e390420ac38caa7c3d70b604e3e6ac6c81158ba4fb8ef9af483f6d32279d33453f49aa0dcde2698dd2a7af20eea07c200c6a5f677d17a9abe99
|
7
|
+
data.tar.gz: 09a37d24790f4fb8e01fb3bb2e8fcef5f5f5b7bf70e52ff16ab5c26bd48dd4f6ebae55b9a357b135c8edb4436fe1018e1ae12ebb710c525a136dc3cd65e71311
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Scott Nielsen
|
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,29 @@
|
|
1
|
+
# EM::Synchrony::DataoneVin
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'em-synchrony-dataone-vin'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install em-synchrony-dataone-vin
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'em-synchrony/dataone-vin/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "em-synchrony-dataone-vin"
|
8
|
+
spec.version = EventMachine::Synchrony::DataoneVin::VERSION
|
9
|
+
spec.authors = ["Scott Nielsen", "Jake Mallory"]
|
10
|
+
spec.email = ["scottnielsen5@gmail.com", "tinomen@gmail.com"]
|
11
|
+
spec.description = %q{A client for the Dataone vindecoding service that runs with EM::Synchrony}
|
12
|
+
spec.summary = %q{A client for the Dataone vindecoding service that runs with EM::Synchrony}
|
13
|
+
spec.homepage = "https://github.com/scizo/em-synchrony-dataone-vin"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "em-http-request", "~> 1.1.0"
|
22
|
+
spec.add_dependency "em-synchrony", "~> 1.0.3"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
+
spec.add_development_dependency "rake", "~> 0.9.6"
|
26
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'em-synchrony/dataone-vin'
|
2
|
+
|
3
|
+
module EventMachine
|
4
|
+
module Synchrony
|
5
|
+
module DataoneVin
|
6
|
+
class VinExploderAdapter
|
7
|
+
class Error < ::StandardError; end
|
8
|
+
|
9
|
+
DRIVELINE_TYPES = {
|
10
|
+
'4x4' => '4WD',
|
11
|
+
'4X4' => '4WD',
|
12
|
+
'4x2' => 'RWD',
|
13
|
+
'4X2' => 'RWD',
|
14
|
+
}
|
15
|
+
|
16
|
+
FUEL_TYPES = {
|
17
|
+
'B' => 'BIODIESEL',
|
18
|
+
'D' => 'DIESEL',
|
19
|
+
'F' => 'FFV',
|
20
|
+
'G' => 'GAS',
|
21
|
+
'I' => 'HYBRID',
|
22
|
+
'L' => 'ELECTRIC',
|
23
|
+
'N' => 'NATURALGAS',
|
24
|
+
'P' => 'PETROLEUM',
|
25
|
+
'Y' => 'HYBRID',
|
26
|
+
}
|
27
|
+
|
28
|
+
BRAKE_TYPES = {
|
29
|
+
['Not Available', 'Not Available'] => 'Non-ABS',
|
30
|
+
['Not Available', 'Standard'] => '4-Wheel ABS',
|
31
|
+
['Not Available', 'Optional'] => 'Non-ABS | 4-Wheel ABS',
|
32
|
+
['Standard', 'Not Available'] => '2-Wheel ABS',
|
33
|
+
['Standard', 'Standard'] => '2-Wheel ABS | 4-Wheel ABS',
|
34
|
+
['Standard', 'Optional'] => '2-Wheel ABS | 4-Wheel ABS',
|
35
|
+
['Optional', 'Not Available'] => 'Non-ABS | 2-Wheel ABS',
|
36
|
+
['Optional', 'Standard'] => '2-Wheel ABS | 4-Wheel ABS',
|
37
|
+
['Optional', 'Optional'] => 'Non-ABS | 2-Wheel ABS | 4-Wheel ABS',
|
38
|
+
}
|
39
|
+
|
40
|
+
DATA_PATHS = {
|
41
|
+
'year' => ['basic_data', 'year'],
|
42
|
+
'make' => ['basic_data', 'make'],
|
43
|
+
'model' => ['basic_data', 'model'],
|
44
|
+
'trim_level' => ['basic_data', 'trim'],
|
45
|
+
'engine_type' => ['engines', 0, 'name'],
|
46
|
+
'engine_displacement' => ['engines', 0, 'displacement'],
|
47
|
+
'engine_shape' => ['engines', 0, 'block_type'],
|
48
|
+
'body_style' => ['basic_data', 'body_type'],
|
49
|
+
'manufactured_in' => ['basic_data', 'country_of_manufacture'],
|
50
|
+
'driveline' => ['basic_data', 'drive_type'],
|
51
|
+
'fuel_type' => ['engines', 0, 'fuel_type'],
|
52
|
+
'transmission-long' => ['transmissions', 0, 'name'],
|
53
|
+
'gears' => ['transmissions', 0, 'gears'],
|
54
|
+
'transmission-type' => ['transmissions', 0, 'type'],
|
55
|
+
'tank' => ['specifications', ['category', 'Fuel Tanks'], 'specifications', ['name', 'Fuel Tank 1 Capacity (Gallons)'], 'value'],
|
56
|
+
'abs_two_wheel' => ['safety_equipment', 'abs_two_wheel'],
|
57
|
+
'abs_four_wheel' => ['safety_equipment', 'abs_four_wheel'],
|
58
|
+
'gvwr_class' => ['specifications', ['category', 'Measurements of Weight'], 'specifications', ['name', 'Gross Vehicle Weight Rating'], 'value'],
|
59
|
+
'vehicle_type' => ['basic_data', 'vehicle_type'],
|
60
|
+
'number_of_cylinders' => ['engines', 0, 'cylinders'],
|
61
|
+
'number_of_doors' => ['basic_data', 'doors'],
|
62
|
+
'standard_seating' => ['specifications', ['category', 'Seating'], 'specifications', ['name', 'Standard Seating'], 'value'],
|
63
|
+
'optional_seating' => ['specifications', ['category', 'Seating'], 'specifications', ['name', 'Max Seating'], 'value'],
|
64
|
+
'length' => ['specifications', ['category', 'Measurements of Size and Shape'], 'specifications', ['name', 'Length'], 'value'],
|
65
|
+
'width' => ['specifications', ['category', 'Measurements of Size and Shape'], 'specifications', ['name', 'Width'], 'value'],
|
66
|
+
'height' => ['specifications', ['category', 'Measurements of Size and Shape'], 'specifications', ['name', 'Height'], 'value'],
|
67
|
+
'production_seq_number' => ['This will always be nil'],
|
68
|
+
}
|
69
|
+
|
70
|
+
def initialize(options)
|
71
|
+
client_id, authorization_code = options.values_at(:client_id, :authorization_code)
|
72
|
+
|
73
|
+
unless client_id && authorization_code
|
74
|
+
raise Error.new "DataoneVin::VinExploderAdapter requires both a client_id and an authorization_code"
|
75
|
+
end
|
76
|
+
|
77
|
+
DataoneVin.configure client_id, authorization_code
|
78
|
+
end
|
79
|
+
|
80
|
+
def explode(vin)
|
81
|
+
format_response DataoneVin.get(vin), vin
|
82
|
+
end
|
83
|
+
|
84
|
+
def format_response(response, vin)
|
85
|
+
errors = errors(response)
|
86
|
+
return {:errors => errors} unless errors.empty?
|
87
|
+
|
88
|
+
data = response['query_responses']['Request-Sample']
|
89
|
+
explosion(data['common_data']).merge \
|
90
|
+
:errors => [],
|
91
|
+
:vin => vin,
|
92
|
+
:vin_key => vin_key(vin),
|
93
|
+
:vendor_result => data
|
94
|
+
end
|
95
|
+
|
96
|
+
def errors(response)
|
97
|
+
query_error = response['query_responses']['Request-Sample']['query_error']['error_message']
|
98
|
+
errors = response['decoder_messages']['decoder_errors']
|
99
|
+
errors << query_error unless query_error.empty?
|
100
|
+
errors
|
101
|
+
end
|
102
|
+
|
103
|
+
def explosion(data)
|
104
|
+
normalize Hash[DATA_PATHS.map do |(key, path)|
|
105
|
+
[key, lookup_data(data, path)]
|
106
|
+
end]
|
107
|
+
end
|
108
|
+
|
109
|
+
def lookup_data(data, path)
|
110
|
+
path.reduce(data) do |d, (k, v)|
|
111
|
+
if v
|
112
|
+
d.find{|h| h[k] == v}
|
113
|
+
else
|
114
|
+
d[k]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
rescue
|
118
|
+
nil
|
119
|
+
end
|
120
|
+
|
121
|
+
def normalize(data)
|
122
|
+
data['driveline'] = normalize_driveline data['driveline']
|
123
|
+
data['fuel_type'] = normalize_fuel_type data['fuel_type']
|
124
|
+
data['vehicle_type'] = data['vehicle_type'].upcase
|
125
|
+
data['has_turbo'] = !!(data['engine_type'] =~ /turbo/i)
|
126
|
+
data['transmission-short'] = "#{data.delete('gears')}#{data.delete('transmission-type')}"
|
127
|
+
data['anti-brake_system'] = normalize_brakes data.delete('abs_two_wheel'), data.delete('abs_four_wheel')
|
128
|
+
data['gvwr_class'] = normalize_gvwr_class data['gvwr_class']
|
129
|
+
|
130
|
+
data
|
131
|
+
end
|
132
|
+
|
133
|
+
def normalize_driveline(driveline)
|
134
|
+
DRIVELINE_TYPES.fetch(driveline, driveline)
|
135
|
+
end
|
136
|
+
|
137
|
+
def normalize_fuel_type(fuel_type)
|
138
|
+
FUEL_TYPES.fetch(fuel_type, 'No data')
|
139
|
+
end
|
140
|
+
|
141
|
+
def normalize_brakes(abs_two_wheel, abs_four_wheel)
|
142
|
+
BRAKE_TYPES.fetch([abs_two_wheel, abs_four_wheel], 'No Data')
|
143
|
+
end
|
144
|
+
|
145
|
+
def normalize_gvwr_class(weight_rating)
|
146
|
+
case weight_rating.to_i
|
147
|
+
when 0..6_000 then '1'
|
148
|
+
when 6_001..10_000 then '2'
|
149
|
+
when 10_001..14_000 then '3'
|
150
|
+
when 14_001..16_000 then '4'
|
151
|
+
when 16_001..19_500 then '5'
|
152
|
+
when 19_501..26_000 then '6'
|
153
|
+
when 26_001..33_000 then '7'
|
154
|
+
when 33_001..Float::INFINITY then '8'
|
155
|
+
else '1'
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def vin_key(vin)
|
160
|
+
"#{vin[0,8]}#{vin[9,2]}"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'em-http'
|
3
|
+
require 'em-synchrony'
|
4
|
+
require 'em-synchrony/em-http'
|
5
|
+
require 'em-synchrony/dataone-vin/version'
|
6
|
+
|
7
|
+
module EventMachine
|
8
|
+
module Synchrony
|
9
|
+
module DataoneVin
|
10
|
+
module_function
|
11
|
+
|
12
|
+
def configure(client_id, authorization_code)
|
13
|
+
@dataone_config = {
|
14
|
+
:client_id => client_id,
|
15
|
+
:authorization_code => authorization_code
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def get(vin)
|
20
|
+
JSON::load EM::HttpRequest.new(request_url).post(
|
21
|
+
:head => {:content_type => 'application/x-www-form-urlencoded'},
|
22
|
+
:body => request_hash(vin)
|
23
|
+
).response
|
24
|
+
end
|
25
|
+
|
26
|
+
def request_url
|
27
|
+
"https://www.dataonesoftware.com/webservices/vindecoder/decode"
|
28
|
+
end
|
29
|
+
|
30
|
+
def request_hash(vin)
|
31
|
+
@dataone_config.merge :decoder_query => decoder_settings(vin)
|
32
|
+
end
|
33
|
+
|
34
|
+
def decoder_settings(vin)
|
35
|
+
JSON::dump \
|
36
|
+
"decoder_settings"=>
|
37
|
+
{"display"=>"full",
|
38
|
+
"version"=>"7.0.0",
|
39
|
+
"styles"=>"on",
|
40
|
+
"style_data_packs"=>
|
41
|
+
{"basic_data"=>"on",
|
42
|
+
"pricing"=>"on",
|
43
|
+
"engines"=>"on",
|
44
|
+
"transmissions"=>"on",
|
45
|
+
"specifications"=>"on",
|
46
|
+
"optional_equipment"=>"on",
|
47
|
+
"colors"=>"on",
|
48
|
+
"safety_equipment"=>"on",
|
49
|
+
"warranties"=>"on"},
|
50
|
+
"common_data"=>"on",
|
51
|
+
"common_data_packs"=>
|
52
|
+
{"basic_data"=>"on",
|
53
|
+
"pricing"=>"on",
|
54
|
+
"engines"=>"on",
|
55
|
+
"transmissions"=>"on",
|
56
|
+
"specifications"=>"on",
|
57
|
+
"colors"=>"on",
|
58
|
+
"safety_equipment"=>"on",
|
59
|
+
"warranties"=>"on"}},
|
60
|
+
"query_requests"=>
|
61
|
+
{"Request-Sample"=>
|
62
|
+
{"vin"=>vin,
|
63
|
+
"year"=>"",
|
64
|
+
"make"=>"",
|
65
|
+
"model"=>"",
|
66
|
+
"trim"=>"",
|
67
|
+
"model_number"=>"",
|
68
|
+
"package_code"=>"",
|
69
|
+
"drive_type"=>"",
|
70
|
+
"vehicle_type"=>"",
|
71
|
+
"body_type"=>"",
|
72
|
+
"body_subtype"=>"",
|
73
|
+
"doors"=>"",
|
74
|
+
"bedlength"=>"",
|
75
|
+
"wheelbase"=>"",
|
76
|
+
"msrp"=>"",
|
77
|
+
"invoice_price"=>"",
|
78
|
+
"engine"=>
|
79
|
+
{"description"=>"",
|
80
|
+
"block_type"=>"",
|
81
|
+
"cylinders"=>"",
|
82
|
+
"displacement"=>"",
|
83
|
+
"fuel_type"=>""},
|
84
|
+
"transmission"=>{"description"=>"", "trans_type"=>"", "trans_speeds"=>""},
|
85
|
+
"optional_equipment_codes"=>"",
|
86
|
+
"installed_equipment_descriptions"=>"",
|
87
|
+
"interior_color"=>{"description"=>"", "color_code"=>""},
|
88
|
+
"exterior_color"=>{"description"=>"", "color_code"=>""}}}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'em-synchrony/dataone-vin/vin_exploder_adapter.rb'
|
3
|
+
|
4
|
+
module EventMachine
|
5
|
+
module Synchrony
|
6
|
+
module DataoneVin
|
7
|
+
describe VinExploderAdapter do
|
8
|
+
include TestHelpers
|
9
|
+
|
10
|
+
let(:adapter) {
|
11
|
+
VinExploderAdapter.new \
|
12
|
+
:client_id => DATAONE_CONFIG[0],
|
13
|
+
:authorization_code => DATAONE_CONFIG[1]
|
14
|
+
}
|
15
|
+
|
16
|
+
it 'should format the raw dataone json to the desired result' do
|
17
|
+
adapter.format_response(expected_result, '1FT7W2BT6BEC91853').must_equal \
|
18
|
+
'year' => '2000',
|
19
|
+
'make' => 'Toyota',
|
20
|
+
'model' => 'Tundra',
|
21
|
+
'trim_level' => 'SR5',
|
22
|
+
'engine_type' => 'ED 4L NA V 8 double overhead cam (DOHC) 32V',
|
23
|
+
'engine_displacement' => '4.7',
|
24
|
+
'engine_shape' => 'V',
|
25
|
+
'body_style' => 'Pickup',
|
26
|
+
'manufactured_in' => '',
|
27
|
+
'driveline' => 'RWD',
|
28
|
+
'fuel_type' => 'GAS',
|
29
|
+
'anti-brake_system' => 'No Data',
|
30
|
+
'gvwr_class' => '2',
|
31
|
+
'transmission-long' => '4-Speed Automatic',
|
32
|
+
'transmission-short' => '4A',
|
33
|
+
'tank' => '26',
|
34
|
+
'vehicle_type' => 'TRUCK',
|
35
|
+
'has_turbo' => false,
|
36
|
+
'number_of_cylinders' => '8',
|
37
|
+
'number_of_doors' => '4',
|
38
|
+
'standard_seating' => '6',
|
39
|
+
'optional_seating' => '6',
|
40
|
+
'length' => '217.5',
|
41
|
+
'width' => '75.2',
|
42
|
+
'height' => '70.5',
|
43
|
+
'production_seq_number' => nil,
|
44
|
+
:errors => [],
|
45
|
+
:vin => '1FT7W2BT6BEC91853',
|
46
|
+
:vin_key => '1FT7W2BTBE',
|
47
|
+
:vendor_result => expected_result['query_responses']['Request-Sample']
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'em-synchrony/dataone-vin'
|
3
|
+
|
4
|
+
module EventMachine
|
5
|
+
module Synchrony
|
6
|
+
describe DataoneVin do
|
7
|
+
include TestHelpers
|
8
|
+
|
9
|
+
before do
|
10
|
+
DataoneVin.configure(*DATAONE_CONFIG)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should work' do
|
14
|
+
EM.synchrony do
|
15
|
+
result = EM::Synchrony::DataoneVin.get('5TBRT3418YS094830')
|
16
|
+
result['query_responses']['Request-Sample'].delete('transaction_id')
|
17
|
+
result.must_equal expected_result
|
18
|
+
EM.stop
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|