deckstrings 0.0.3 → 1.0.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 +4 -4
- data/README.md +69 -5
- data/lib/deckstrings/deckstrings.rb +135 -51
- data/lib/deckstrings/enum.rb +1 -3
- data/lib/deckstrings/varint.rb +1 -1
- metadata +17 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a5a397bdd301581b9c7e06931ad8f123bab9c6f1
|
|
4
|
+
data.tar.gz: 12821a30968d65f31d565dd3b0542263e453d263
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 76acb89402c69393cc41ca7a5a5a65e2dd02c85d1bfa7962e9c78ef7edf3b894407640cd106686e627ec1a0b047e1f2432af00a7f5067b5a55e9a09f97d2c4f1
|
|
7
|
+
data.tar.gz: ecf7998ac4975afd1382631a11b81c722e2d33816d63217154aaeffa29f8f2c72be85e7a9132bb1874a0c4fd03ed35aff765e9c32265eb109137b0566e470d24
|
data/README.md
CHANGED
|
@@ -20,7 +20,7 @@ For additional entity metadata (e.g. hero class, card cost, card name), the DBF
|
|
|
20
20
|
|
|
21
21
|
## Decoding
|
|
22
22
|
|
|
23
|
-
`Deckstrings::decode`
|
|
23
|
+
[`Deckstrings::decode`](http://www.rubydoc.info/gems/deckstrings/Deckstrings#decode-class_method) decodes a deckstring with basic validation.
|
|
24
24
|
|
|
25
25
|
```ruby
|
|
26
26
|
deckstring = 'AAECAZICCPIF+Az5DK6rAuC7ApS9AsnHApnTAgtAX/4BxAbkCLS7Asu8As+8At2+AqDNAofOAgA='
|
|
@@ -31,11 +31,11 @@ puts Deckstrings::decode(deckstring)
|
|
|
31
31
|
{:format=>2, :heroes=>[274], :cards=>{754=>1, 1656=>1, 1657=>1, 38318=>1, 40416=>1, 40596=>1, 41929=>1, 43417=>1, 64=>2, 95=>2, 254=>2, 836=>2, 1124=>2, 40372=>2, 40523=>2, 40527=>2, 40797=>2, 42656=>2, 42759=>2}}
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
`Deckstrings::Deck.
|
|
34
|
+
[`Deckstrings::Deck.decode`](http://www.rubydoc.info/gems/deckstrings/Deckstrings/Deck#decode-class_method) decodes a deckstring with extended validation and additional deck information including card names and costs.
|
|
35
35
|
|
|
36
36
|
```ruby
|
|
37
37
|
deckstring = 'AAECAZICCPIF+Az5DK6rAuC7ApS9AsnHApnTAgtAX/4BxAbkCLS7Asu8As+8At2+AqDNAofOAgA='
|
|
38
|
-
puts Deckstrings::Deck.
|
|
38
|
+
puts Deckstrings::Deck.decode(deckstring)
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
```text
|
|
@@ -66,9 +66,73 @@ Hero: Malfurion Stormrage
|
|
|
66
66
|
|
|
67
67
|
## Encoding
|
|
68
68
|
|
|
69
|
-
`Deckstrings::encode`
|
|
69
|
+
[`Deckstrings::encode`](http://www.rubydoc.info/gems/deckstrings/Deckstrings#encode-class_method) encodes deck information in a deckstring with basic validation.
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
```ruby
|
|
72
|
+
puts Deckstrings::encode(
|
|
73
|
+
format: Deckstrings::Format.standard,
|
|
74
|
+
heroes: [Deckstrings::Hero.malfurion],
|
|
75
|
+
cards: {
|
|
76
|
+
254 => 2,
|
|
77
|
+
40372 => 2,
|
|
78
|
+
1124 => 2,
|
|
79
|
+
836 => 2,
|
|
80
|
+
40523 => 2,
|
|
81
|
+
64 => 2,
|
|
82
|
+
40527 => 2,
|
|
83
|
+
38318 => 1,
|
|
84
|
+
754 => 1,
|
|
85
|
+
95 => 2,
|
|
86
|
+
1657 => 1,
|
|
87
|
+
42656 => 2,
|
|
88
|
+
1656 => 1,
|
|
89
|
+
40596 => 1,
|
|
90
|
+
40797 => 2,
|
|
91
|
+
43417 => 1,
|
|
92
|
+
41929 => 1,
|
|
93
|
+
42759 => 2,
|
|
94
|
+
40416 => 1
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
AAECAZICCPIF+Az5DK6rAuC7ApS9AsnHApnTAgtAX/4BxAbkCLS7Asu8As+8At2+AqDNAofOAgA=
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
[`Deckstrings::Deck.encode`](http://www.rubydoc.info/gems/deckstrings/Deckstrings/Deck#encode-class_method) encodes deck information in a deckstring with extended validation.
|
|
104
|
+
|
|
105
|
+
```ruby
|
|
106
|
+
puts Deckstrings::Deck.encode(
|
|
107
|
+
format: 2,
|
|
108
|
+
heroes: [274],
|
|
109
|
+
cards: {
|
|
110
|
+
254 => 2,
|
|
111
|
+
40372 => 2,
|
|
112
|
+
1124 => 2,
|
|
113
|
+
836 => 2,
|
|
114
|
+
40523 => 2,
|
|
115
|
+
64 => 2,
|
|
116
|
+
40527 => 2,
|
|
117
|
+
38318 => 1,
|
|
118
|
+
754 => 1,
|
|
119
|
+
95 => 2,
|
|
120
|
+
1657 => 1,
|
|
121
|
+
42656 => 2,
|
|
122
|
+
1656 => 1,
|
|
123
|
+
40596 => 1,
|
|
124
|
+
40797 => 2,
|
|
125
|
+
43417 => 1,
|
|
126
|
+
41929 => 1,
|
|
127
|
+
42759 => 2,
|
|
128
|
+
40416 => 1
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
AAECAZICCPIF+Az5DK6rAuC7ApS9AsnHApnTAgtAX/4BxAbkCLS7Asu8As+8At2+AqDNAofOAgA=
|
|
135
|
+
```
|
|
72
136
|
|
|
73
137
|
## License
|
|
74
138
|
|
|
@@ -2,10 +2,8 @@ require 'base64'
|
|
|
2
2
|
require 'json'
|
|
3
3
|
|
|
4
4
|
module Deckstrings
|
|
5
|
+
# An error indicating a malformed deckstring.
|
|
5
6
|
class FormatError < StandardError
|
|
6
|
-
def initialize(message)
|
|
7
|
-
super(message)
|
|
8
|
-
end
|
|
9
7
|
end
|
|
10
8
|
|
|
11
9
|
# Enumeration of valid format types: wild and standard.
|
|
@@ -21,6 +19,7 @@ module Deckstrings
|
|
|
21
19
|
define :standard, 2, 'Standard'
|
|
22
20
|
end
|
|
23
21
|
|
|
22
|
+
# Enumeration of all nine Hearthstone classes.
|
|
24
23
|
class HeroClass
|
|
25
24
|
include Enum
|
|
26
25
|
|
|
@@ -92,6 +91,7 @@ module Deckstrings
|
|
|
92
91
|
@id = id
|
|
93
92
|
@name = name
|
|
94
93
|
@hero_class = HeroClass.parse(hero_class)
|
|
94
|
+
raise ArgumentError, "Invalid hero class: #{hero_class}." if @hero_class.nil?
|
|
95
95
|
end
|
|
96
96
|
|
|
97
97
|
# @return [Hero] Jaina Proudmoore.
|
|
@@ -231,8 +231,8 @@ module Deckstrings
|
|
|
231
231
|
Hero.new(id, hero['name'], hero['class'])
|
|
232
232
|
end
|
|
233
233
|
|
|
234
|
-
# @see https://hearthstonejson.com/ HearthstoneJSON for hero metadata.
|
|
235
234
|
# @return [Integer] Hearthstone DBF ID of the hero.
|
|
235
|
+
# @see https://hearthstonejson.com/ HearthstoneJSON
|
|
236
236
|
attr_reader :id
|
|
237
237
|
|
|
238
238
|
# @return [String] Name of the hero.
|
|
@@ -243,7 +243,7 @@ module Deckstrings
|
|
|
243
243
|
end
|
|
244
244
|
|
|
245
245
|
# A Hearthstone card with basic metadata.
|
|
246
|
-
# @see Deck.
|
|
246
|
+
# @see Deck.decode
|
|
247
247
|
class Card
|
|
248
248
|
def initialize(id, name, cost)
|
|
249
249
|
@id = id
|
|
@@ -251,8 +251,8 @@ module Deckstrings
|
|
|
251
251
|
@cost = cost
|
|
252
252
|
end
|
|
253
253
|
|
|
254
|
-
# @see https://hearthstonejson.com/ HearthstoneJSON for card metadata.
|
|
255
254
|
# @return [Integer] Hearthstone DBF ID of the card.
|
|
255
|
+
# @see https://hearthstonejson.com/ HearthstoneJSON
|
|
256
256
|
attr_reader :id
|
|
257
257
|
|
|
258
258
|
# @return [String] Name of the card.
|
|
@@ -262,50 +262,103 @@ module Deckstrings
|
|
|
262
262
|
attr_reader :cost
|
|
263
263
|
end
|
|
264
264
|
|
|
265
|
-
# A Hearthstone deck convertible to and from a deckstring.
|
|
266
|
-
# @see Deck.
|
|
267
|
-
# @see Deck
|
|
265
|
+
# A Hearthstone deck with metadata that is convertible to and from a deckstring.
|
|
266
|
+
# @see Deck.decode
|
|
267
|
+
# @see Deck.encode
|
|
268
268
|
class Deck
|
|
269
|
+
# Create a new deck from component parts.
|
|
270
|
+
# @param format [Integer, Deckstrings::Format] Format for this deck: wild or standard.
|
|
271
|
+
# @param heroes [Array<Integer, Deckstrings::Hero>] Heroes for this deck. Multiple heroes are supported, but typically
|
|
272
|
+
# this array will contain one element.
|
|
273
|
+
# @param cards [Hash{Integer, Deckstrings::Card => Integer}] Cards in the deck. A Hash from card ID to its instance count in the deck.
|
|
274
|
+
# @raise [ArgumentError] If format, heroes, or any cards are unknown.
|
|
269
275
|
def initialize(format:, heroes:, cards:)
|
|
270
|
-
# TODO: Translate RangeError -> FormatError.
|
|
271
|
-
|
|
272
276
|
@format = Format.parse(format) if !format.is_a?(Format)
|
|
273
|
-
if !@format
|
|
274
|
-
raise FormatError.new("Unknown format: #{format}.")
|
|
275
|
-
end
|
|
277
|
+
raise ArgumentError, "Unknown format: #{format}." if !@format
|
|
276
278
|
|
|
277
279
|
@heroes = heroes.map do |id|
|
|
278
280
|
hero = Database.instance.heroes[id]
|
|
279
|
-
raise
|
|
281
|
+
raise ArgumentError, "Unknown hero: #{id}." if hero.nil?
|
|
280
282
|
Hero.new(id, hero['name'], hero['class'])
|
|
281
283
|
end
|
|
282
284
|
|
|
283
285
|
@cards = cards.map do |id, count|
|
|
284
286
|
card = Database.instance.cards[id]
|
|
285
|
-
raise
|
|
287
|
+
raise ArgumentError, "Unknown card: #{id}." if card.nil?
|
|
286
288
|
[Card.new(id, card['name'], card['cost']), count]
|
|
287
289
|
end.sort_by { |card, _| card.cost }.to_h
|
|
288
290
|
end
|
|
289
291
|
|
|
290
|
-
#
|
|
291
|
-
# @
|
|
292
|
+
# Raw deck details.
|
|
293
|
+
# @return [{ format: Integer, heroes: Array<Integer>, cards: Hash{Integer => Integer} }] See {Deckstrings.decode} for details.
|
|
294
|
+
# @see Deckstrings.decode
|
|
292
295
|
def raw
|
|
293
296
|
heroes = @heroes.map(&:id)
|
|
294
297
|
cards = @cards.map { |card, count| [card.id, count] }.to_h
|
|
295
298
|
{ format: @format.value, heroes: heroes, cards: cards }
|
|
296
299
|
end
|
|
297
300
|
|
|
301
|
+
# Encoded deckstring for this deck.
|
|
298
302
|
# @return [String] Base64-encoded compact byte string representing the deck.
|
|
303
|
+
# @see Deckstrings.encode
|
|
299
304
|
# @see .encode
|
|
300
305
|
def deckstring
|
|
301
306
|
return Deckstrings::encode(self.raw)
|
|
302
307
|
end
|
|
303
308
|
|
|
304
|
-
#
|
|
305
|
-
#
|
|
306
|
-
|
|
309
|
+
# Decodes a Hearthstone deckstring into a {Deck} with basic hero and card metadata.
|
|
310
|
+
#
|
|
311
|
+
# This method validates the well-formedness of the deckstring, the embedded version, the format, card counts, and
|
|
312
|
+
# each hero/card ID.
|
|
313
|
+
#
|
|
314
|
+
# All IDs refer to unique Hearthstone DBF IDs which can be used in conjunction with [HearthstoneJSON metadata](https://hearthstonejson.com/).
|
|
315
|
+
# @example
|
|
316
|
+
# deck = Deckstrings::Deck.decode('AAEBAf0GAA/yAaIC3ALgBPcE+wWKBs4H2QexCMII2Q31DfoN9g4A')
|
|
317
|
+
# @example
|
|
318
|
+
# deck = Deckstrings::Deck.decode('AAECAZICCPIF+Az5DK6rAuC7ApS9AsnHApnTAgtAX/4BxAbkCLS7Asu8As+8At2+AqDNAofOAgA=')
|
|
319
|
+
# @param deckstring [String] Base64-encoded Hearthstone deckstring.
|
|
320
|
+
# @raise [FormatError] If the deckstring is malformed or contains invalid deck data.
|
|
321
|
+
# @return [Deck] Decoded Hearthstone deck.
|
|
322
|
+
# @see Deckstrings.decode
|
|
323
|
+
# @see Deck.encode
|
|
324
|
+
# @see https://hearthstonejson.com/ HearthstoneJSON
|
|
325
|
+
def self.decode(deckstring)
|
|
307
326
|
parts = Deckstrings::decode(deckstring)
|
|
308
|
-
|
|
327
|
+
begin
|
|
328
|
+
Deck.new(parts)
|
|
329
|
+
rescue ArgumentError => e
|
|
330
|
+
raise FormatError, e.to_s
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
# Encodes a Hearthstone deck as a compact deckstring.
|
|
335
|
+
#
|
|
336
|
+
# This method validates card counts, format, and each hero/card ID.
|
|
337
|
+
#
|
|
338
|
+
# All IDs refer to unique Hearthstone DBF IDs which can be seen in [HearthstoneJSON metadata](https://hearthstonejson.com/).
|
|
339
|
+
# @example
|
|
340
|
+
# deckstring = Deckstrings::Deck.encode(format: 2, heroes: [637], cards: { 1004 => 2, 315 => 2 })
|
|
341
|
+
# @example
|
|
342
|
+
# deckstring = Deckstrings::Deck.encode(
|
|
343
|
+
# format: Deckstrings::Format.standard,
|
|
344
|
+
# heroes: [Deckstrings::Hero.mage],
|
|
345
|
+
# cards: { 1004 => 2, 315 => 2 }
|
|
346
|
+
# )
|
|
347
|
+
# @param format [Integer, Deckstrings::Format] Format for this deck: wild or standard.
|
|
348
|
+
# @param heroes [Array<Integer, Deckstrings::Hero>] Heroes for this deck. Multiple heroes are supported, but typically
|
|
349
|
+
# this array will contain one element.
|
|
350
|
+
# @param cards [Hash{Integer, Deckstrings::Card => Integer}] Cards in the deck. A Hash from card ID to its instance count in the deck.
|
|
351
|
+
# @raise [FormatError] If any card counts are less than 1, or if any IDs do not refer to valid Hearthstone entities.
|
|
352
|
+
# @return [String] Base64-encoded compact byte string representing the deck.
|
|
353
|
+
# @see .encode
|
|
354
|
+
# @see Deck.decode
|
|
355
|
+
# @see https://hearthstonejson.com/ HearthstoneJSON
|
|
356
|
+
def self.encode(format:, heroes:, cards:)
|
|
357
|
+
begin
|
|
358
|
+
Deck.new(format: format, heroes: heroes, cards: cards).deckstring
|
|
359
|
+
rescue ArgumentError => e
|
|
360
|
+
raise FormatError, e.to_s
|
|
361
|
+
end
|
|
309
362
|
end
|
|
310
363
|
|
|
311
364
|
# @return [Boolean] `true` if the deck is Wild format, `false` otherwise.
|
|
@@ -320,6 +373,9 @@ module Deckstrings
|
|
|
320
373
|
format.standard?
|
|
321
374
|
end
|
|
322
375
|
|
|
376
|
+
# Pretty-printed deck listing.
|
|
377
|
+
# @example
|
|
378
|
+
# puts Deckstrings::Deck.decode('AAECAZICCPIF+Az5DK6rAuC7ApS9AsnHApnTAgtAX/4BxAbkCLS7Asu8As+8At2+AqDNAofOAgA=')
|
|
323
379
|
# @example
|
|
324
380
|
# Format: Standard
|
|
325
381
|
# Class: Druid
|
|
@@ -346,41 +402,57 @@ module Deckstrings
|
|
|
346
402
|
# 1× Kun the Forgotten King
|
|
347
403
|
# @return [String] A pretty-printed listing of deck details.
|
|
348
404
|
def to_s
|
|
405
|
+
listing = "Format: #{format}"
|
|
406
|
+
|
|
349
407
|
hero = @heroes.first
|
|
350
|
-
|
|
351
|
-
"#{
|
|
352
|
-
end
|
|
408
|
+
if hero
|
|
409
|
+
listing += "\nClass: #{hero.hero_class}\nHero: #{hero.name}"
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
if !cards.empty?
|
|
413
|
+
listing += "\n\n" + cards.map { |card, count| "#{count}× #{card.name}" }.join("\n")
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
listing
|
|
353
417
|
end
|
|
354
418
|
|
|
355
419
|
# @return [Format] Format for this deck.
|
|
356
420
|
attr_reader :format
|
|
357
421
|
|
|
358
|
-
#
|
|
422
|
+
# The heroes associated with this deck.
|
|
423
|
+
# @return [Array<Hero>] Typically, this array will contain one element.
|
|
359
424
|
attr_reader :heroes
|
|
360
425
|
|
|
361
|
-
#
|
|
426
|
+
# The cards contained in this deck.
|
|
427
|
+
# @return [Hash{Card => Integer}] A Hash from {Card} to its instance count in the deck.
|
|
362
428
|
attr_reader :cards
|
|
363
429
|
end
|
|
364
430
|
|
|
365
431
|
using VarIntExtensions
|
|
366
432
|
|
|
367
433
|
# Encodes a Hearthstone deck as a compact deckstring.
|
|
434
|
+
#
|
|
435
|
+
# This method validates card counts, but does not validate the format or individual hero/card IDs. For stricter validation,
|
|
436
|
+
# see {Deck.encode}.
|
|
437
|
+
#
|
|
438
|
+
# All IDs refer to unique Hearthstone DBF IDs which can be seen in [HearthstoneJSON metadata](https://hearthstonejson.com/).
|
|
368
439
|
# @example
|
|
369
|
-
# Deckstrings
|
|
440
|
+
# deckstring = Deckstrings::encode(format: 2, heroes: [637], cards: { 1004 => 2, 315 => 2 })
|
|
370
441
|
# @example
|
|
371
|
-
# Deckstrings
|
|
442
|
+
# deckstring = Deckstrings::encode(
|
|
372
443
|
# format: Deckstrings::Format.standard,
|
|
373
|
-
# heroes: [Deckstrings::Hero.
|
|
374
|
-
# cards: {
|
|
444
|
+
# heroes: [Deckstrings::Hero.mage],
|
|
445
|
+
# cards: { 1004 => 2, 315 => 2 }
|
|
375
446
|
# )
|
|
376
447
|
# @param format [Integer, Deckstrings::Format] Format for this deck: wild or standard.
|
|
377
448
|
# @param heroes [Array<Integer, Deckstrings::Hero>] Heroes for this deck. Multiple heroes are supported, but typically
|
|
378
449
|
# this array will contain one element.
|
|
379
|
-
# @param cards [Hash{Integer, Deckstrings::Card => Integer}] Cards in the deck.
|
|
380
|
-
# @raise [
|
|
450
|
+
# @param cards [Hash{Integer, Deckstrings::Card => Integer}] Cards in the deck. A Hash from card ID to its instance count in the deck.
|
|
451
|
+
# @raise [FormatError] If any card counts are less than 1.
|
|
381
452
|
# @return [String] Base64-encoded compact byte string representing the deck.
|
|
382
|
-
# @see Deck
|
|
453
|
+
# @see Deck.encode
|
|
383
454
|
# @see .decode
|
|
455
|
+
# @see https://hearthstonejson.com/ HearthstoneJSON
|
|
384
456
|
def self.encode(format:, heroes:, cards:)
|
|
385
457
|
stream = StringIO.new('')
|
|
386
458
|
|
|
@@ -403,7 +475,7 @@ module Deckstrings
|
|
|
403
475
|
|
|
404
476
|
invalid = by_count.keys.select { |count| count < 1 }
|
|
405
477
|
unless invalid.empty?
|
|
406
|
-
raise
|
|
478
|
+
raise FormatError, "Invalid card count: #{invalid.join(', ')}."
|
|
407
479
|
end
|
|
408
480
|
|
|
409
481
|
1.upto(3) do |count|
|
|
@@ -415,10 +487,15 @@ module Deckstrings
|
|
|
415
487
|
end
|
|
416
488
|
end
|
|
417
489
|
|
|
418
|
-
Base64::
|
|
490
|
+
Base64::strict_encode64(stream.string).strip
|
|
419
491
|
end
|
|
420
492
|
|
|
421
|
-
# Decodes a Hearthstone deckstring into format, hero, and card
|
|
493
|
+
# Decodes a Hearthstone deckstring into format, hero, and card counts.
|
|
494
|
+
#
|
|
495
|
+
# This method validates the well-formedness of the deckstring and the embedded version, but does not validate
|
|
496
|
+
# the format, individual hero/card IDs, or card counts. For stricter validation and additional deck info, see {Deck.decode}.
|
|
497
|
+
#
|
|
498
|
+
# All IDs refer to unique Hearthstone DBF IDs which can be used in conjunction with [HearthstoneJSON metadata](https://hearthstonejson.com/).
|
|
422
499
|
# @example
|
|
423
500
|
# deck = Deckstrings::decode('AAEBAf0GAA/yAaIC3ALgBPcE+wWKBs4H2QexCMII2Q31DfoN9g4A')
|
|
424
501
|
# @example
|
|
@@ -426,24 +503,31 @@ module Deckstrings
|
|
|
426
503
|
# @param deckstring [String] Base64-encoded Hearthstone deckstring.
|
|
427
504
|
# @raise [FormatError] If the deckstring is malformed or contains invalid deck data.
|
|
428
505
|
# @return [{ format: Integer, heroes: Array<Integer>, cards: Hash{Integer => Integer} }] Parsed Hearthstone deck details.
|
|
429
|
-
#
|
|
506
|
+
# `heroes` is an array of hero IDs, but this will usually be just one element. `cards` is a
|
|
507
|
+
# Hash from card ID to its instance count in the deck.
|
|
508
|
+
# @see Deck.decode
|
|
430
509
|
# @see .encode
|
|
510
|
+
# @see https://hearthstonejson.com/ HearthstoneJSON
|
|
431
511
|
def self.decode(deckstring)
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
end
|
|
512
|
+
if deckstring.nil? || deckstring.empty?
|
|
513
|
+
raise FormatError, 'Invalid deckstring.'
|
|
514
|
+
end
|
|
436
515
|
|
|
437
|
-
|
|
516
|
+
stream = begin
|
|
517
|
+
StringIO.new(Base64::strict_decode64(deckstring))
|
|
518
|
+
rescue ArgumentError
|
|
519
|
+
raise FormatError, 'Invalid base64-encoded string.'
|
|
520
|
+
end
|
|
438
521
|
|
|
522
|
+
begin
|
|
439
523
|
reserved = stream.read_varint
|
|
440
524
|
if reserved != 0
|
|
441
|
-
raise FormatError
|
|
525
|
+
raise FormatError, "Unexpected reserved byte: #{reserved}."
|
|
442
526
|
end
|
|
443
527
|
|
|
444
528
|
version = stream.read_varint
|
|
445
529
|
if version != 1
|
|
446
|
-
raise FormatError
|
|
530
|
+
raise FormatError, "Unexpected version: #{version}."
|
|
447
531
|
end
|
|
448
532
|
|
|
449
533
|
format = stream.read_varint
|
|
@@ -464,14 +548,14 @@ module Deckstrings
|
|
|
464
548
|
cards[card] = i < 3 ? i : stream.read_varint
|
|
465
549
|
end
|
|
466
550
|
end
|
|
467
|
-
|
|
468
|
-
return {
|
|
469
|
-
format: format,
|
|
470
|
-
heroes: heroes,
|
|
471
|
-
cards: cards
|
|
472
|
-
}
|
|
473
551
|
rescue EOFError
|
|
474
552
|
raise FormatError, 'Unexpected end of data.'
|
|
475
553
|
end
|
|
554
|
+
|
|
555
|
+
return {
|
|
556
|
+
format: format,
|
|
557
|
+
heroes: heroes,
|
|
558
|
+
cards: cards
|
|
559
|
+
}
|
|
476
560
|
end
|
|
477
561
|
end
|
data/lib/deckstrings/enum.rb
CHANGED
data/lib/deckstrings/varint.rb
CHANGED
metadata
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: deckstrings
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chris Schmich
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-09-
|
|
12
|
-
dependencies:
|
|
11
|
+
date: 2017-09-16 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: yard
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0.9'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0.9'
|
|
13
27
|
description: Ruby library for encoding and decoding Hearthstone deckstrings.
|
|
14
28
|
email: schmch@gmail.com
|
|
15
29
|
executables: []
|