backpack_tf 0.8.1 → 0.8.4
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 +4 -4
- data/backpack_tf.gemspec +4 -4
- data/lib/backpack_tf/assets/attribute_controlled_attached_particles.json +667 -0
- data/lib/backpack_tf/client.rb +5 -5
- data/lib/backpack_tf/item.rb +29 -19
- data/lib/backpack_tf/item_price.rb +100 -16
- data/lib/backpack_tf/response.rb +3 -0
- data/lib/backpack_tf/version.rb +1 -1
- data/spec/backpack_tf/client_spec.rb +7 -0
- data/spec/backpack_tf/currency_spec.rb +62 -58
- data/spec/backpack_tf/inherited_class_methods_spec.rb +100 -0
- data/spec/backpack_tf/item_price_spec.rb +106 -42
- data/spec/backpack_tf/item_spec.rb +89 -128
- data/spec/backpack_tf/price_spec.rb +7 -22
- data/spec/backpack_tf/response_spec.rb +16 -3
- data/spec/backpack_tf/special_item_spec.rb +34 -29
- data/spec/backpack_tf/user_listing_spec.rb +22 -24
- data/spec/backpack_tf/user_spec.rb +28 -30
- data/spec/fixtures/item_crate.json +65 -0
- data/spec/fixtures/item_typical.json +1 -1
- data/spec/fixtures/item_unusual.json +1 -1
- data/spec/fixtures/item_with_unconventional_structure.json +1 -1
- data/spec/fixtures/item_without_defindex.json +1 -1
- data/spec/spec_helper.rb +47 -0
- metadata +9 -24
data/lib/backpack_tf/client.rb
CHANGED
@@ -34,19 +34,19 @@ module BackpackTF
|
|
34
34
|
|
35
35
|
def self.build_url_via action, query_options = {}
|
36
36
|
case action
|
37
|
-
when :get_prices, :prices
|
37
|
+
when :get_prices, :prices, :price
|
38
38
|
version = 4
|
39
39
|
interface_url = "/#{Price.interface}/v#{version}/?"
|
40
|
-
when :get_currencies, :currencies
|
40
|
+
when :get_currencies, :currencies, :currency
|
41
41
|
version = 1
|
42
42
|
interface_url = "/#{Currency.interface}/v#{version}/?"
|
43
|
-
when :get_special_items, :special_items
|
43
|
+
when :get_special_items, :special_items, :special_item, :specialitem
|
44
44
|
version = 1
|
45
45
|
interface_url = "/#{SpecialItem.interface}/v#{version}/?"
|
46
|
-
when :get_users, :users
|
46
|
+
when :get_users, :users, :user
|
47
47
|
version = 3
|
48
48
|
interface_url = "/#{User.interface}/v#{version}/?"
|
49
|
-
when :get_user_listings, :user_listing, :
|
49
|
+
when :get_user_listings, :user_listings, :user_listing, :userlisting
|
50
50
|
version = 1
|
51
51
|
interface_url = "/#{UserListing.interface}/v#{version}/?"
|
52
52
|
else
|
data/lib/backpack_tf/item.rb
CHANGED
@@ -19,11 +19,17 @@ module BackpackTF
|
|
19
19
|
attr = JSON.parse(attr)
|
20
20
|
end
|
21
21
|
|
22
|
-
@defindex = attr['defindex']
|
23
|
-
@prices =
|
22
|
+
@defindex = process_defindex(attr['defindex'])
|
23
|
+
@prices = generate_prices_hash(attr)
|
24
24
|
end
|
25
25
|
|
26
|
-
def
|
26
|
+
def process_defindex arr
|
27
|
+
return nil if arr.length == 0
|
28
|
+
return arr[0] if arr.length == 1
|
29
|
+
arr
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate_prices_hash input_hash
|
27
33
|
|
28
34
|
raise TypeError, 'expecting a Hash object' unless input_hash.class == Hash
|
29
35
|
unless input_hash.has_key? 'prices'
|
@@ -34,6 +40,7 @@ module BackpackTF
|
|
34
40
|
prices = input_hash['prices']
|
35
41
|
|
36
42
|
prices.inject({}) do |hash, (key, val)|
|
43
|
+
|
37
44
|
quality = BackpackTF::ItemPrice.qualities[key.to_i]
|
38
45
|
new_key = [quality.to_s]
|
39
46
|
|
@@ -43,31 +50,34 @@ module BackpackTF
|
|
43
50
|
craftability = prices[key][tradability].keys.first
|
44
51
|
new_key << craftability
|
45
52
|
|
46
|
-
new_key = new_key.join(
|
53
|
+
new_key = new_key.join(ItemPrice::KEYNAME_DELIMITER)
|
47
54
|
|
48
55
|
prefix = prices[key][tradability][craftability]
|
49
56
|
|
50
|
-
if prefix.
|
51
|
-
item_prices = prefix
|
57
|
+
if (prefix.length <= 1)
|
58
|
+
item_prices = prefix[0]
|
59
|
+
# patch for oddly-structured items, ie: Aqua Summer 2013 Cooler
|
60
|
+
item_prices = prefix.values.first if item_prices.nil?
|
61
|
+
|
52
62
|
item_price_obj = ItemPrice.new(new_key, item_prices)
|
53
63
|
hash[new_key] = item_price_obj
|
54
|
-
elsif
|
55
|
-
|
56
|
-
item_prices = prefix
|
57
|
-
item_price_obj = ItemPrice.new(new_key, item_prices)
|
58
|
-
hash[
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
64
|
+
elsif key == '5' # item with 'Unusual' quality
|
65
|
+
prefix.keys.each do |prefix_key|
|
66
|
+
item_prices = prefix[prefix_key]
|
67
|
+
item_price_obj = ItemPrice.new(new_key, item_prices, prefix_key)
|
68
|
+
hash[item_price_obj.effect] = item_price_obj
|
69
|
+
end
|
70
|
+
else # a Crate
|
71
|
+
prefix.keys.each do |prefix_key|
|
72
|
+
temp_key = "#{new_key}_##{prefix_key.to_i}"
|
73
|
+
item_prices = prefix[prefix_key]
|
74
|
+
item_price_obj = ItemPrice.new(temp_key, item_prices, prefix_key)
|
75
|
+
hash[temp_key] = item_price_obj
|
66
76
|
end
|
67
77
|
end
|
68
|
-
|
69
78
|
hash
|
70
79
|
end
|
80
|
+
|
71
81
|
end
|
72
82
|
|
73
83
|
end
|
@@ -2,13 +2,14 @@ module BackpackTF
|
|
2
2
|
|
3
3
|
class ItemPrice
|
4
4
|
|
5
|
+
KEYNAME_DELIMITER = '_'
|
6
|
+
PARTICLE_EFFECTS_KEY = 'attribute_controlled_attached_particles'
|
7
|
+
PARTICLE_EFFECTS_FILE = "./lib/backpack_tf/assets/#{PARTICLE_EFFECTS_KEY}.json"
|
8
|
+
|
5
9
|
###########################
|
6
10
|
# Class Methods
|
7
11
|
###########################
|
8
12
|
|
9
|
-
@@required_keys = ['currency', 'value', 'last_update', 'difference']
|
10
|
-
def self.required_keys; @@required_keys; end
|
11
|
-
|
12
13
|
# mapping official API quality integers to quality names
|
13
14
|
# https://wiki.teamfortress.com/wiki/WebAPI/GetSchema#Result_Data
|
14
15
|
@@qualities = [
|
@@ -29,11 +30,51 @@ module BackpackTF
|
|
29
30
|
:"Collector's"
|
30
31
|
]
|
31
32
|
|
32
|
-
def self.qualities; @@qualities; end
|
33
|
-
|
34
33
|
@@tradabilities = [:Tradable, :'Non-Tradable']
|
35
34
|
@@craftabilities = [:Craftable, :'Non-Craftable']
|
36
|
-
|
35
|
+
@@required_keys = ['currency', 'value', 'last_update', 'difference']
|
36
|
+
|
37
|
+
def self.qualities; @@qualities; end
|
38
|
+
def self.required_keys; @@required_keys; end
|
39
|
+
|
40
|
+
def self.quality_name_to_index q
|
41
|
+
@@qualities.index(q.to_sym) unless q.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.hash_particle_effects
|
45
|
+
|
46
|
+
file = File.open(PARTICLE_EFFECTS_FILE).read
|
47
|
+
effects_arr = JSON.parse(file)[PARTICLE_EFFECTS_KEY]
|
48
|
+
|
49
|
+
effects_arr.inject({}) do |hash, pe|
|
50
|
+
id = pe['id']
|
51
|
+
name = pe['name']
|
52
|
+
hash[id] = name
|
53
|
+
hash
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
@@particle_effects = self.hash_particle_effects
|
59
|
+
def self.particle_effects; @@particle_effects; end
|
60
|
+
|
61
|
+
def self.ins_sp str
|
62
|
+
str = str.split('')
|
63
|
+
new_str = ''
|
64
|
+
str.each_with_index do |c, i|
|
65
|
+
if i == 0
|
66
|
+
new_str += c
|
67
|
+
else
|
68
|
+
unless c == c.upcase && str[i-1] == str[i-1].upcase
|
69
|
+
new_str += c
|
70
|
+
else
|
71
|
+
new_str += (' ' + c)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
new_str
|
76
|
+
end
|
77
|
+
|
37
78
|
###########################
|
38
79
|
# Instance Methods
|
39
80
|
###########################
|
@@ -56,24 +97,24 @@ module BackpackTF
|
|
56
97
|
attr_reader :value_raw
|
57
98
|
# @return [Float] The item's value in the lowest currency without rounding. Reques raw to be enabled and set to 2
|
58
99
|
attr_reader :value_high_raw
|
59
|
-
# @return [Fixnum]
|
100
|
+
# @return [Fixnum] A timestamp of when the price was last updated
|
60
101
|
attr_reader :last_update
|
61
|
-
# @return [Fixnum]
|
102
|
+
# @return [Fixnum] A relative difference between the former price and the current price. If 0, assume new price.
|
62
103
|
attr_reader :difference
|
104
|
+
# @return [String] Result of @@particle_effects[@priceindex]
|
105
|
+
attr_reader :effect
|
63
106
|
|
64
107
|
def initialize key, attr, priceindex = nil
|
65
108
|
attr = JSON.parse(attr) unless attr.class == Hash
|
66
|
-
unless self.class.required_keys.all? {|k| attr.keys.member? k }
|
67
|
-
raise KeyError, "The passed-in hash is required to have at least these 4 keys: #{self.class.required_keys.join(', ')}"
|
68
|
-
end
|
69
109
|
|
70
|
-
|
110
|
+
key = key.split(KEYNAME_DELIMITER)
|
111
|
+
key = process_key(key)
|
71
112
|
|
72
|
-
|
113
|
+
validate_attributes(attr)
|
73
114
|
|
74
|
-
@quality =
|
75
|
-
@tradability =
|
76
|
-
@craftability =
|
115
|
+
@quality = key[0]
|
116
|
+
@tradability = key[1]
|
117
|
+
@craftability = key[2]
|
77
118
|
@currency = attr['currency'].to_sym
|
78
119
|
@value = attr['value']
|
79
120
|
@value_high = attr['value_high']
|
@@ -81,6 +122,49 @@ module BackpackTF
|
|
81
122
|
@value_high_raw = attr['value_high_raw']
|
82
123
|
@last_update = attr['last_update']
|
83
124
|
@difference = attr['difference']
|
125
|
+
@priceindex = priceindex
|
126
|
+
@effect = self.class.particle_effects[priceindex.to_i]
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
# requires the key to an Array with length of 3 or more
|
131
|
+
# converts each element to a Symbol object
|
132
|
+
# The 3 bits of info are subject to a NameError if any one of them is invalid
|
133
|
+
# @return [Array] an Array of Symbol objects
|
134
|
+
# @raises NameError, ArgumentError
|
135
|
+
def process_key key
|
136
|
+
|
137
|
+
unless key.length >= 3
|
138
|
+
raise ArgumentError, "This key must have a length of 3 or greater"
|
139
|
+
end
|
140
|
+
|
141
|
+
key.map! { |bit| bit.to_sym }
|
142
|
+
|
143
|
+
unless @@qualities.include? key[0]
|
144
|
+
raise NameError, 'Must include a valid Quality'
|
145
|
+
end
|
146
|
+
unless @@tradabilities.include? key[1]
|
147
|
+
raise NameError, 'Must include a valid Tradability'
|
148
|
+
end
|
149
|
+
unless @@craftabilities.include? key[2]
|
150
|
+
raise NameError, 'Must include a valid Craftability'
|
151
|
+
end
|
152
|
+
|
153
|
+
key
|
154
|
+
end
|
155
|
+
|
156
|
+
def validate_attributes attributes
|
157
|
+
|
158
|
+
raise TypeError unless attributes.class == Hash
|
159
|
+
|
160
|
+
unless @@required_keys.all? { |k| attributes.keys.member? k }
|
161
|
+
msg = "The passed-in hash is required to have at least these 4 keys: "
|
162
|
+
msg += "#{self.class.required_keys.join(', ')}"
|
163
|
+
raise KeyError, msg
|
164
|
+
end
|
165
|
+
|
166
|
+
attributes
|
167
|
+
|
84
168
|
end
|
85
169
|
|
86
170
|
end
|
data/lib/backpack_tf/response.rb
CHANGED
data/lib/backpack_tf/version.rb
CHANGED
@@ -100,6 +100,13 @@ module BackpackTF
|
|
100
100
|
expect(Currency.currencies).to be_nil
|
101
101
|
end
|
102
102
|
|
103
|
+
after :each do
|
104
|
+
Response.responses(:reset => :confirm)
|
105
|
+
expect(Response.responses).to be_empty
|
106
|
+
expect(Currency.response).to be_nil
|
107
|
+
expect(Currency.currencies).to be_nil
|
108
|
+
end
|
109
|
+
|
103
110
|
let(:fetched_currencies) {
|
104
111
|
bp.fetch(:currencies, {:compress => 1, :appid => 440})
|
105
112
|
}
|
@@ -16,70 +16,57 @@ module BackpackTF
|
|
16
16
|
Response.hash_keys_to_sym(fixture)
|
17
17
|
}
|
18
18
|
|
19
|
-
it '
|
20
|
-
expect(described_class).to respond_to :responses, :response, :currencies, :interface, :hash_keys_to_sym
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'has these default attributes' do
|
19
|
+
it 'class has these default attributes' do
|
24
20
|
expect(described_class.interface).to eq :IGetCurrencies
|
25
21
|
end
|
26
22
|
|
27
|
-
describe '::
|
28
|
-
|
29
|
-
|
30
|
-
stub_http_response_with('currencies.json')
|
31
|
-
opts = { :app_id => 440, :compress => 1 }
|
32
|
-
fetched_currencies = bp.fetch(:currencies, opts)
|
33
|
-
Response.responses(described_class.to_sym => fetched_currencies)
|
34
|
-
end
|
35
|
-
|
36
|
-
context 'access from Response class' do
|
37
|
-
it 'Currency can be accessed by calling the key, Currency' do
|
38
|
-
expect(Response.responses[:'BackpackTF::Currency']).to eq json_obj
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
context 'access from Currency class' do
|
43
|
-
it 'can access response information via the class method, ::response' do
|
44
|
-
expect(described_class.response).to eq json_obj
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'is the same as calling Currency.response' do
|
49
|
-
expect(Response.responses[:'BackpackTF::Currency']).to eq Currency.response
|
23
|
+
describe '::response' do
|
24
|
+
before :all do
|
25
|
+
expect(described_class.response).to be_nil
|
50
26
|
end
|
51
|
-
end
|
52
27
|
|
53
|
-
describe '::response' do
|
54
28
|
before :each do
|
55
29
|
stub_http_response_with('currencies.json')
|
56
|
-
|
57
|
-
|
58
|
-
Response.responses(':BackpackTF::Currency' => fetched_currencies)
|
30
|
+
fetched_currencies = bp.fetch(:currencies)
|
31
|
+
bp.update(described_class, fetched_currencies)
|
59
32
|
end
|
60
|
-
|
61
|
-
|
33
|
+
|
34
|
+
after :all do
|
35
|
+
Response.responses(:reset => :confirm)
|
36
|
+
expect(Response.responses).to be_empty
|
37
|
+
expect(described_class.response).to be_nil
|
38
|
+
expect(described_class.currencies).to be_nil
|
62
39
|
end
|
63
40
|
|
64
41
|
it 'the keys of the response attribute should have these values' do
|
65
|
-
|
66
|
-
expect(
|
67
|
-
expect(
|
68
|
-
expect(
|
69
|
-
expect(
|
42
|
+
response = described_class.response
|
43
|
+
expect(response[:success]).to eq 1
|
44
|
+
expect(response[:message]).to eq nil
|
45
|
+
expect(response[:current_time]).to eq 1430784460
|
46
|
+
expect(response[:name]).to eq 'Team Fortress 2'
|
47
|
+
expect(response[:url]).to eq 'http://backpack.tf'
|
70
48
|
end
|
71
|
-
|
72
49
|
end
|
73
50
|
|
74
51
|
describe '::currencies' do
|
52
|
+
before :all do
|
53
|
+
expect(described_class.response).to be_nil
|
54
|
+
expect(described_class.currencies).to be_nil
|
55
|
+
end
|
56
|
+
|
75
57
|
before :each do
|
76
58
|
Response.responses(:reset => :confirm)
|
77
59
|
expect(Response.responses).to be_empty
|
78
60
|
|
79
61
|
stub_http_response_with('currencies.json')
|
80
|
-
|
81
|
-
|
82
|
-
|
62
|
+
fetched_currencies = bp.fetch(:currencies)
|
63
|
+
bp.update(described_class, fetched_currencies)
|
64
|
+
end
|
65
|
+
|
66
|
+
after :all do
|
67
|
+
Response.responses(:reset => :confirm)
|
68
|
+
expect(Response.responses).to be_empty
|
69
|
+
described_class.class_eval { @currencies = nil }
|
83
70
|
end
|
84
71
|
|
85
72
|
it 'returns the fixture and sets to @@currencies variable' do
|
@@ -96,26 +83,43 @@ module BackpackTF
|
|
96
83
|
end
|
97
84
|
end
|
98
85
|
|
99
|
-
describe '
|
86
|
+
describe '#initialize' do
|
87
|
+
|
88
|
+
before :all do
|
89
|
+
expect(described_class.response).to be_nil
|
90
|
+
expect(described_class.currencies).to be_nil
|
91
|
+
end
|
100
92
|
|
101
|
-
|
93
|
+
before :each do
|
94
|
+
bp.update(described_class, json_obj)
|
95
|
+
expect(described_class.currencies).not_to be_nil
|
96
|
+
end
|
102
97
|
|
103
|
-
|
104
|
-
|
98
|
+
after :all do
|
99
|
+
Response.responses(:reset => :confirm)
|
100
|
+
expect(Response.responses).to be_empty
|
101
|
+
described_class.class_eval { @currencies = nil }
|
105
102
|
end
|
106
103
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
expect(
|
113
|
-
expect(metal.craftable).to eq :Craftable
|
114
|
-
expect(metal.tradable).to eq :Tradable
|
115
|
-
expect(metal.defindex).to eq 5002
|
116
|
-
expect(metal.blanket).to eq 0
|
104
|
+
subject {
|
105
|
+
described_class.new(:metal, described_class.currencies[:metal])
|
106
|
+
}
|
107
|
+
|
108
|
+
it 'instance should respond to these methods' do
|
109
|
+
expect(subject).to respond_to(:quality, :priceindex, :single, :plural, :round, :craftable, :tradable, :defindex, :blanket)
|
117
110
|
end
|
118
111
|
|
112
|
+
it 'instance should have these values' do
|
113
|
+
expect(subject.quality).to eq 6
|
114
|
+
expect(subject.priceindex).to eq 0
|
115
|
+
expect(subject.single).to eq 'ref'
|
116
|
+
expect(subject.plural).to eq 'ref'
|
117
|
+
expect(subject.round).to eq 2
|
118
|
+
expect(subject.craftable).to eq :Craftable
|
119
|
+
expect(subject.tradable).to eq :Tradable
|
120
|
+
expect(subject.defindex).to eq 5002
|
121
|
+
expect(subject.blanket).to eq 0
|
122
|
+
end
|
119
123
|
end
|
120
124
|
|
121
125
|
end
|