runeterra_cards 0.2.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +0 -1
- data/doc/CHANGELOG.md +37 -2
- data/doc/README.md +2 -2
- data/lib/runeterra_cards.rb +9 -2
- data/lib/runeterra_cards/{card_and_count.rb → card.rb} +7 -11
- data/lib/runeterra_cards/card_metadata.rb +9 -3
- data/lib/runeterra_cards/card_set.rb +53 -16
- data/lib/runeterra_cards/cost.rb +94 -0
- data/lib/runeterra_cards/errors.rb +25 -5
- data/lib/runeterra_cards/factions.rb +4 -0
- data/lib/runeterra_cards/metadata.rb +11 -0
- data/lib/runeterra_cards/version.rb +2 -1
- metadata +34 -19
- data/doc/version_helper.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 143a6e1907badc2fc066202446fa5106a8ddfda903e195b4fadd2a8c45fcc824
|
4
|
+
data.tar.gz: '0669ded1c45362335feddb5f5f8846407f61a85a04a458877fb728ace2a99cc1'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88a8a01c7a0971da6c084210bbd0b5121add3faf6dd5b28ac12c1235ad5023adeda8729af3fe8b96479a895aab48769a87b81dddabe9d662cc15514cf003ebe6
|
7
|
+
data.tar.gz: 289070859e22694e9014fad41b6fce31a867489541080644c4a98adee6fa87afa653a08ea68cdbe536af3fe3a9875386b508e0f73d0b1301f98152cf3d5203fd
|
data/.yardopts
CHANGED
data/doc/CHANGELOG.md
CHANGED
@@ -4,13 +4,48 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
+
## [0.5.0] - 2021-03-05
|
8
|
+
### Added
|
9
|
+
- Support for the Shurima faction.
|
10
|
+
- Support for version 3 deck codes.
|
11
|
+
- A new Card class to represent cards on their own without a count.
|
12
|
+
- CardSet#as_cards, which returns all the cards in the set as Cards.
|
13
|
+
- CardSet#as_card_codes, which returns all the cards in the set as card codes.
|
14
|
+
|
15
|
+
### Removed
|
16
|
+
- RuneterraCards.from_card_and_counts method.
|
17
|
+
- CardAndCount class (replaced by the new Card class).
|
18
|
+
- CardSet#as_card_and_counts (replaced by #as_cards).
|
19
|
+
|
20
|
+
### Deprecated
|
21
|
+
- CardSet#cards – the signature of this method will be changing in a future version to match #as_cards, migrate to #as_card_codes to keep the current #cards behaviour.
|
22
|
+
|
23
|
+
## [0.4.1] - 2021-02-05
|
24
|
+
### Fixed
|
25
|
+
|
26
|
+
- Fixed issue where card numbers > 127 came out extremely wrong, e.g. Aphelios and several other of the new cards ([issue #4](https://github.com/zofrex/runeterra_cards/issues/4)).
|
27
|
+
|
28
|
+
## [0.4.0] - 2020-12-08
|
29
|
+
### Added
|
30
|
+
- [`CardMetadata` now has a `#cost` attribute representing the mana cost of a card.](https://github.com/zofrex/runeterra_cards/pull/3) (thanks, [nieszkah](https://github.com/alpm)!) Technically this is backwards-compatibility breaking as it makes a new field in metadata json mandatory.
|
31
|
+
|
32
|
+
## [0.3.0] - 2020-08-31
|
33
|
+
### Added
|
34
|
+
- `Cost` class to represent crafting cost as wildcards & shards.
|
35
|
+
- `Metadata#cost_of` to get the cost of crafting a `CardSet`.
|
36
|
+
- Documented everything that is public & non-deprecated.
|
37
|
+
|
38
|
+
## [0.2.3] - 2020-08-31
|
39
|
+
### Fixed
|
40
|
+
- Fixed issue with documentation not rendering on rubydoc.info.
|
41
|
+
|
7
42
|
## [0.2.2] - 2020-08-30
|
8
43
|
### Fixed
|
9
|
-
- Included .yardopts in the Gem so README and CHANGELOG get included in documentation generated from the Gem
|
44
|
+
- Included .yardopts in the Gem so README and CHANGELOG get included in documentation generated from the Gem.
|
10
45
|
|
11
46
|
## [0.2.1] - 2020-08-29
|
12
47
|
### Fixed
|
13
|
-
- Correctly packaged README and CHANGELOG in the Gem
|
48
|
+
- Correctly packaged README and CHANGELOG in the Gem.
|
14
49
|
|
15
50
|
## [0.2.0] - 2020-08-29
|
16
51
|
### Added
|
data/doc/README.md
CHANGED
@@ -9,13 +9,13 @@ This library makes it easy to decode Legends of Runeterra deck codes, load Data
|
|
9
9
|
Add the following to your `Gemfile`:
|
10
10
|
|
11
11
|
```
|
12
|
-
gem 'runeterra_cards', '~>
|
12
|
+
gem 'runeterra_cards', '~> 0.5.0'
|
13
13
|
```
|
14
14
|
|
15
15
|
Or, if you're building a Gem, your `.gemspec`:
|
16
16
|
|
17
17
|
```
|
18
|
-
spec.add_dependency 'runeterra_cards', '~>
|
18
|
+
spec.add_dependency 'runeterra_cards', '~> 0.5.0'
|
19
19
|
```
|
20
20
|
|
21
21
|
## Updates & Versioning
|
data/lib/runeterra_cards.rb
CHANGED
@@ -3,12 +3,19 @@
|
|
3
3
|
require 'runeterra_cards/version'
|
4
4
|
require 'runeterra_cards/errors'
|
5
5
|
require 'runeterra_cards/factions'
|
6
|
-
require 'runeterra_cards/
|
6
|
+
require 'runeterra_cards/card'
|
7
7
|
require 'runeterra_cards/card_metadata'
|
8
8
|
require 'runeterra_cards/metadata'
|
9
9
|
require 'runeterra_cards/card_set'
|
10
|
+
require 'runeterra_cards/cost'
|
10
11
|
|
12
|
+
# The top-level module for +runeterra_cards+.
|
13
|
+
#
|
14
|
+
# Some of the most useful classes are {CardSet} and {Metadata}.
|
15
|
+
#
|
16
|
+
# You might also want to check out the {file:doc/README.md} and the {file:doc/CHANGELOG.md}.
|
11
17
|
module RuneterraCards
|
12
18
|
# The version of deck encoding supported
|
13
|
-
SUPPORTED_VERSION =
|
19
|
+
SUPPORTED_VERSION = 3
|
20
|
+
public_constant :SUPPORTED_VERSION
|
14
21
|
end
|
@@ -1,22 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module RuneterraCards
|
4
|
-
# Represents a card
|
4
|
+
# Represents a card
|
5
5
|
# @deprecated
|
6
|
-
class
|
6
|
+
class Card
|
7
7
|
# The card code, for example "01DE123"
|
8
8
|
# @return [String]
|
9
9
|
attr_reader :code
|
10
10
|
|
11
|
-
# How many of this card are in a collection (between 1-3).
|
12
|
-
# @return [Fixnum]
|
13
|
-
attr_reader :count
|
14
|
-
|
15
11
|
# @param set [Fixnum]
|
16
12
|
# @param faction_number [Fixnum]
|
17
13
|
# @param card_number [Fixnum]
|
18
|
-
|
19
|
-
def initialize(code: nil, count:, set: nil, faction_number: nil, card_number: nil)
|
14
|
+
def initialize(code: nil, set: nil, faction_number: nil, card_number: nil)
|
20
15
|
if code
|
21
16
|
raise if set || faction_number || card_number
|
22
17
|
|
@@ -27,15 +22,16 @@ module RuneterraCards
|
|
27
22
|
padded_card_number = format('%<i>03d', i: card_number)
|
28
23
|
@code = "#{padded_set}#{faction}#{padded_card_number}"
|
29
24
|
end
|
30
|
-
@count = count
|
31
25
|
end
|
32
26
|
|
27
|
+
#:nodoc:
|
33
28
|
def eql?(other)
|
34
|
-
code.eql?(other.code)
|
29
|
+
code.eql?(other.code)
|
35
30
|
end
|
36
31
|
|
32
|
+
#:nodoc:
|
37
33
|
def hash
|
38
|
-
|
34
|
+
code.hash
|
39
35
|
end
|
40
36
|
end
|
41
37
|
end
|
@@ -26,6 +26,10 @@ module RuneterraCards
|
|
26
26
|
# @return [String]
|
27
27
|
attr_reader :card_code
|
28
28
|
|
29
|
+
# Returns the cost attribute. For example: 3.
|
30
|
+
# @return [Fixnum]
|
31
|
+
attr_reader :cost
|
32
|
+
|
29
33
|
# Returns the card's rarity as a symbol. Can be one of: +:none+, +:common+, +:rare+, +:epic+, or +:champion+
|
30
34
|
# @return [Symbol]
|
31
35
|
attr_reader :rarity
|
@@ -38,12 +42,15 @@ module RuneterraCards
|
|
38
42
|
# @option hash [String] name
|
39
43
|
# @option hash [String] cardCode
|
40
44
|
# @option hash [Boolean] collectible
|
45
|
+
# @option hash [Fixnum] cost
|
46
|
+
# @option hash [String] rarityRef
|
41
47
|
#
|
42
48
|
# @raise [MissingCardDataError] if any of the expected hash parameters are missing, or if +rarityRef+ contains an
|
43
49
|
# unexpected value.
|
44
50
|
def initialize(hash)
|
45
51
|
begin
|
46
|
-
@name, @card_code, @collectible, rarity_ref =
|
52
|
+
@name, @card_code, @collectible, @cost, rarity_ref =
|
53
|
+
hash.fetch_values('name', 'cardCode', 'collectible', 'cost', 'rarityRef')
|
47
54
|
rescue KeyError => e
|
48
55
|
raise MetadataLoadError.new(hash['name'] || hash['cardCode'], "Missing expected key: #{e.key}")
|
49
56
|
end
|
@@ -51,8 +58,7 @@ module RuneterraCards
|
|
51
58
|
@rarity = RARITIES[rarity_ref]
|
52
59
|
return unless rarity.nil?
|
53
60
|
|
54
|
-
raise MetadataLoadError.
|
55
|
-
"expected one of: #{RARITIES.keys.join ', '}")
|
61
|
+
raise MetadataLoadError.invalid_rarity(name, rarity_ref, RARITIES.keys)
|
56
62
|
end
|
57
63
|
|
58
64
|
# Whether or not the card is collectible.
|
@@ -7,41 +7,60 @@ module RuneterraCards
|
|
7
7
|
#
|
8
8
|
# @todo The API to this class is very unstable and will change a lot in a coming release.
|
9
9
|
class CardSet
|
10
|
+
# Extract this bitmask so Mutant can't see it, until this fix is released https://github.com/mbj/mutant/pull/1218
|
11
|
+
HIGH_BIT = 0b1000_0000
|
12
|
+
private_constant :HIGH_BIT
|
13
|
+
|
14
|
+
# @return [Hash{String => Number}]
|
15
|
+
# @deprecated
|
10
16
|
attr_reader :cards
|
11
17
|
|
18
|
+
# @param [Hash{String => Number},Enumerable{String => Number}] cards A Hash of card codes mapping to card counts
|
12
19
|
def initialize(cards)
|
13
20
|
@cards = cards
|
14
21
|
end
|
15
22
|
|
16
|
-
#
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
23
|
+
# Subtract another {CardSet CardSet} from this one. Items with count 0 are not represented in the returned
|
24
|
+
# {CardSet CardSet}, they are removed altogether.
|
25
|
+
# @param [CardSet] other An object that responds to {#count_for_card_code}
|
26
|
+
# @return [CardSet]
|
21
27
|
def -(other)
|
22
|
-
remaining_cards =
|
23
|
-
|
24
|
-
|
25
|
-
|
28
|
+
remaining_cards =
|
29
|
+
cards.each_with_object({}) do |(code, count), result|
|
30
|
+
new_count = count - other.count_for_card_code(code)
|
31
|
+
result[code] = new_count unless new_count.equal?(0)
|
32
|
+
end
|
26
33
|
|
27
34
|
CardSet.new(remaining_cards)
|
28
35
|
end
|
29
36
|
|
30
|
-
# @return
|
31
|
-
|
32
|
-
|
33
|
-
cards.map { |code, count| CardAndCount.new(code: code, count: count) }
|
37
|
+
# @return [Enumerable<Card => Number>]
|
38
|
+
def as_cards
|
39
|
+
cards.transform_keys { |code| Card.new(code: code) }
|
34
40
|
end
|
35
41
|
|
42
|
+
# Return all cards in the card set as a map of card codes to counts.
|
43
|
+
# @example
|
44
|
+
# set.as_card_codes #=> { '01DE044' => 1, '02NX003' => 2 }
|
45
|
+
# @return [Enumerable<String => Number>]
|
46
|
+
def as_card_codes
|
47
|
+
cards
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns how many of the given card are in this CardSet.
|
51
|
+
# @param [String] code Card code, e.g. "01DE031"
|
52
|
+
# @return [Integer] How many of the card are in this CardSet, or 0 if it isn't present.
|
36
53
|
def count_for_card_code(code)
|
37
54
|
cards[code] || 0
|
38
55
|
end
|
39
56
|
|
57
|
+
# Parse a Deck Code.
|
40
58
|
# @param deck_code [String]
|
41
59
|
# @raise [Base32Error] if the deck code cannot be Base32 decoded.
|
42
60
|
# @raise [UnrecognizedVersionError] if the deck code's version is not supported by this library
|
43
61
|
# (see {SUPPORTED_VERSION}).
|
44
62
|
# @raise [EmptyInputError] if the deck code is an empty string.
|
63
|
+
# @return [CardSet]
|
45
64
|
def self.from_deck_code(deck_code)
|
46
65
|
binary_data = decode_base32(deck_code)
|
47
66
|
format, version = decode_format_and_version(binary_data[0])
|
@@ -50,9 +69,10 @@ module RuneterraCards
|
|
50
69
|
|
51
70
|
raise unless format.equal? 1
|
52
71
|
|
53
|
-
int_array = binary_data[1..]
|
72
|
+
int_array = unpack_big_endian_varint(binary_data[1..])
|
54
73
|
cards = assemble_card_list(int_array)
|
55
|
-
|
74
|
+
|
75
|
+
new(cards.to_h)
|
56
76
|
end
|
57
77
|
|
58
78
|
# @param string [String] base32-encoded string
|
@@ -80,6 +100,8 @@ module RuneterraCards
|
|
80
100
|
|
81
101
|
private_class_method :decode_format_and_version
|
82
102
|
|
103
|
+
# @param [Array<Fixnum>] array
|
104
|
+
# @return [Array<Card>]
|
83
105
|
def self.assemble_card_list(array)
|
84
106
|
3.downto(1).flat_map do |number_of_copies|
|
85
107
|
set_faction_combination_count = array.shift
|
@@ -87,12 +109,27 @@ module RuneterraCards
|
|
87
109
|
number_of_cards, set, faction = array.shift(3)
|
88
110
|
|
89
111
|
array.shift(number_of_cards).map do |card_number|
|
90
|
-
|
112
|
+
cac = Card.new(set: set, faction_number: faction, card_number: card_number)
|
113
|
+
[cac.code, number_of_copies]
|
91
114
|
end
|
92
115
|
end
|
93
116
|
end
|
94
117
|
end
|
95
118
|
|
96
119
|
private_class_method :assemble_card_list
|
120
|
+
|
121
|
+
# @param [String] binary
|
122
|
+
# @return [Enumerable<Fixnum>]
|
123
|
+
def self.unpack_big_endian_varint(binary)
|
124
|
+
binary.each_byte.slice_after { |b| (b & HIGH_BIT).zero? }.map do |int_bytes|
|
125
|
+
acc = 0
|
126
|
+
int_bytes.each_with_index do |byte, index|
|
127
|
+
acc += (byte & 0b0111_1111) << (7 * index)
|
128
|
+
end
|
129
|
+
acc
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
private_class_method :unpack_big_endian_varint
|
97
134
|
end
|
98
135
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuneterraCards
|
4
|
+
# Represents the cost of a {CardSet}, as wildcards or shards.
|
5
|
+
# To get the cost of a {CardSet} you need to call {Metadata#cost_of}, as rarity (and therefore cost) is a property
|
6
|
+
# of metadata.
|
7
|
+
#
|
8
|
+
# A {Cost} object tells you how many wildcards would be needed to craft a {CardSet}, or alternatively how many
|
9
|
+
# shards would be needed. You can figure out the cost of a mixture of wildcards and shards by creating a new {Cost}
|
10
|
+
# object representing the wildcards to be spent, and subtracting that from the original {Cost} object.
|
11
|
+
#
|
12
|
+
# @example Getting the shard cost for a {CardSet}
|
13
|
+
# cost = metadata.cost_of(card_set)
|
14
|
+
# cost.shards #=> 3000
|
15
|
+
#
|
16
|
+
# @example Getting wildcard costs for a {CardSet}
|
17
|
+
# cost = metadata.cost_of(card_set)
|
18
|
+
# cost.common #=> 3
|
19
|
+
# cost.rare #=> 1
|
20
|
+
# # etc
|
21
|
+
#
|
22
|
+
# @example Getting remaining cost after spending some wildcards
|
23
|
+
# cost = metadata.cost_of(card_set)
|
24
|
+
# cost.dust #=> 11500
|
25
|
+
#
|
26
|
+
# wildcards_in_hand = Cost.new(10, 5, 3, 1)
|
27
|
+
# remaining_cost = cost - wildcards_in_hand
|
28
|
+
# remaining_cost.dust #=> 5100
|
29
|
+
class Cost
|
30
|
+
# The number of Common wildcards needed
|
31
|
+
# @return [Fixnum] count
|
32
|
+
attr_reader :common
|
33
|
+
|
34
|
+
# The number of Rare wildcards needed
|
35
|
+
# @return [Fixnum] count
|
36
|
+
attr_reader :rare
|
37
|
+
|
38
|
+
# The number of Epic wildcards needed
|
39
|
+
# @return [Fixnum] count
|
40
|
+
attr_reader :epic
|
41
|
+
|
42
|
+
# The number of Champion wildcards needed
|
43
|
+
# @return [Fixnum] count
|
44
|
+
attr_reader :champion
|
45
|
+
|
46
|
+
# @param [Fixnum] common
|
47
|
+
# @param [Fixnum] rare
|
48
|
+
# @param [Fixnum] epic
|
49
|
+
# @param [Fixnum] champion
|
50
|
+
def initialize(common, rare, epic, champion)
|
51
|
+
@common, @rare, @epic, @champion = common, rare, epic, champion
|
52
|
+
end
|
53
|
+
|
54
|
+
# The number of shards needed. I.e. the equivalent amount of shards for all these wildcards.
|
55
|
+
# @return [Fixnum] shards
|
56
|
+
def shards
|
57
|
+
common * 100 +
|
58
|
+
rare * 300 +
|
59
|
+
epic * 1200 +
|
60
|
+
champion * 3000
|
61
|
+
end
|
62
|
+
|
63
|
+
# Whether this Cost is equal to another. Equality means exactly the same number of each wildcard, not just the
|
64
|
+
# same shard count.
|
65
|
+
# @param [Cost] other an object that response to {#common}, {#rare}, {#epic}, and {#champion}.
|
66
|
+
# @return [Boolean] equal?
|
67
|
+
def ==(other)
|
68
|
+
common.equal?(other.common) &&
|
69
|
+
rare.equal?(other.rare) &&
|
70
|
+
epic.equal?(other.epic) &&
|
71
|
+
champion.equal?(other.champion)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Subtracts another Cost from this one. Subtraction is performed by subtracting each wildcard type individually,
|
75
|
+
# not by operating on the shard count. The minimum value any wildcard will have is zero, so +5 - 7 = 0+ for
|
76
|
+
# example.
|
77
|
+
# @note This will not return negative values.
|
78
|
+
# @param [Cost] other an object that response to {#common}, {#rare}, {#epic}, and {#champion}.
|
79
|
+
# @return [Cost] The remaining cost, with a floor of 0.
|
80
|
+
# @example
|
81
|
+
# minuend = Cost.new(9, 8, 5, 2)
|
82
|
+
# subtrahend = Cost.new(7, 8, 2, 3)
|
83
|
+
# result = minuend - subtrahend
|
84
|
+
# result #=> Cost.new(2, 0, 3, 0)
|
85
|
+
def -(other)
|
86
|
+
Cost.new(
|
87
|
+
[common - other.common, 0].max,
|
88
|
+
[rare - other.rare, 0].max,
|
89
|
+
[epic - other.epic, 0].max,
|
90
|
+
[champion - other.champion, 0].max
|
91
|
+
)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -8,14 +8,17 @@ module RuneterraCards
|
|
8
8
|
# This exception is raised if the deck code cannot be Base32-decoded. This probably means it isn't a deck code, or
|
9
9
|
# got malformed somehow.
|
10
10
|
class Base32Error < DeckCodeParseError
|
11
|
+
# Returns a new instance of Base32Error with a helpful error message preloaded.
|
11
12
|
def initialize
|
12
|
-
super(
|
13
|
+
super(
|
14
|
+
'Encountered an error while Base32 decoding deck code.' \
|
13
15
|
' Probably an invalid deck code, or possibly a bug in the Base32 handling.')
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
17
19
|
# This exception is raised if the deck code is an empty string.
|
18
20
|
class EmptyInputError < DeckCodeParseError
|
21
|
+
# Returns a new instance of EmptyInputError with a helpful error message preloaded.
|
19
22
|
def initialize
|
20
23
|
super('The input was an empty string')
|
21
24
|
end
|
@@ -32,9 +35,12 @@ module RuneterraCards
|
|
32
35
|
# @return [Fixnum] the version number encountered in the deck code
|
33
36
|
attr_accessor :version
|
34
37
|
|
38
|
+
# @param [Fixnum] expected The version number we were expecting to see in the deck code.
|
39
|
+
# @param [Fixnum] got The version number we actually got.
|
35
40
|
def initialize(expected, got)
|
36
|
-
super(
|
37
|
-
|
41
|
+
super(
|
42
|
+
"Unrecognized deck code version number: #{got}, was expecting: #{expected}. "\
|
43
|
+
'Possibly an invalid deck code, possibly you need to update the deck code library version.')
|
38
44
|
@version = got
|
39
45
|
end
|
40
46
|
end
|
@@ -50,8 +56,10 @@ Possibly an invalid deck code, possibly you need to update the deck code library
|
|
50
56
|
# @return [Fixnum] the faction number that was unrecognized
|
51
57
|
attr_reader :faction_number
|
52
58
|
|
59
|
+
# @param [Fixnum] faction_number The faction number we encountered and did not recognise.
|
53
60
|
def initialize(faction_number)
|
54
|
-
super(
|
61
|
+
super(
|
62
|
+
"Unrecognized faction number '#{faction_number}'."\
|
55
63
|
' Possibly you need to update this library to a newer version')
|
56
64
|
@faction_number = faction_number
|
57
65
|
end
|
@@ -61,7 +69,7 @@ Possibly an invalid deck code, possibly you need to update the deck code library
|
|
61
69
|
# The message will tell you what data was not right, and the {#card} attribute will tell you which card had issues,
|
62
70
|
# if possible.
|
63
71
|
#
|
64
|
-
# @see CardMetadata#initialize
|
72
|
+
# @see CardMetadata#initialize CardMetadata#initialize for details on when this error is raised.
|
65
73
|
class MetadataLoadError < StandardError
|
66
74
|
# Return the name or card code of the card that was missing an expected attribute.
|
67
75
|
# @return [String] name if the name was present
|
@@ -69,6 +77,8 @@ Possibly an invalid deck code, possibly you need to update the deck code library
|
|
69
77
|
# @return [nil] if neither name nor card code were present
|
70
78
|
attr_reader :card
|
71
79
|
|
80
|
+
# @param [String] card The card's name or cardCode.
|
81
|
+
# @param [String] problem Details on the problem encountered loading the card.
|
72
82
|
def initialize(card, problem)
|
73
83
|
if card.nil?
|
74
84
|
super("Error loading data for unknown card (no code or name): #{problem}")
|
@@ -77,5 +87,15 @@ Possibly an invalid deck code, possibly you need to update the deck code library
|
|
77
87
|
end
|
78
88
|
@card = card
|
79
89
|
end
|
90
|
+
|
91
|
+
# Create a {MetadataLoadError MetadataLoadError} with a helpful message regarding an invalid value for rarityRef.
|
92
|
+
# @param [String] card The card name that had an invalid rarityRef value.
|
93
|
+
#
|
94
|
+
# @param [String] given The value that rarityRef had.
|
95
|
+
# @param [Enumerable<String>] expected A list of values that would have been valid.
|
96
|
+
# @return [MetadataLoadError]
|
97
|
+
def self.invalid_rarity(card, given, expected)
|
98
|
+
new(card, "Invalid value for rarityRef, got: #{given}, expected one of: #{expected.join ', '}")
|
99
|
+
end
|
80
100
|
end
|
81
101
|
end
|
@@ -13,8 +13,10 @@ module RuneterraCards
|
|
13
13
|
4 => 'PZ',
|
14
14
|
5 => 'SI',
|
15
15
|
6 => 'BW',
|
16
|
+
7 => 'SH',
|
16
17
|
9 => 'MT',
|
17
18
|
}.freeze
|
19
|
+
public_constant :FACTION_IDENTIFIERS_FROM_INT
|
18
20
|
|
19
21
|
# A map from two-letter Faction identifiers to their integer identifiers
|
20
22
|
# @example
|
@@ -28,6 +30,8 @@ module RuneterraCards
|
|
28
30
|
'PZ' => 4,
|
29
31
|
'SI' => 5,
|
30
32
|
'BW' => 6,
|
33
|
+
'SH' => 7,
|
31
34
|
'MT' => 9,
|
32
35
|
}.freeze
|
36
|
+
public_constant :FACTION_INTS_FROM_IDENTIFIER
|
33
37
|
end
|
@@ -20,6 +20,7 @@ module RuneterraCards
|
|
20
20
|
# @note This class cannot yet handle metadata for multiple locales at the same time. You will need multiple instances
|
21
21
|
# of this class, one for each locale, if you wish to handle multiple locales at this time.
|
22
22
|
class Metadata
|
23
|
+
# Create a new, empty, metadata repository.
|
23
24
|
def initialize
|
24
25
|
@cards = {}
|
25
26
|
end
|
@@ -57,5 +58,15 @@ module RuneterraCards
|
|
57
58
|
def full_set
|
58
59
|
CardSet.new(all_collectible.keys.each_with_object({}) { |code, result| result[code] = 3 })
|
59
60
|
end
|
61
|
+
|
62
|
+
# @param [CardSet] card_set
|
63
|
+
# @return [Cost] the cost of crafting all the cards in the supplied CardSet
|
64
|
+
def cost_of(card_set)
|
65
|
+
rarity_and_count = card_set.cards.map { |card, count| [lookup_card(card).rarity, count] }
|
66
|
+
total = { common: 0, rare: 0, epic: 0, champion: 0 }
|
67
|
+
rarity_and_count.each { |(rarity, count)| total[rarity] += count }
|
68
|
+
|
69
|
+
Cost.new(total.fetch(:common), total.fetch(:rare), total.fetch(:epic), total.fetch(:champion))
|
70
|
+
end
|
60
71
|
end
|
61
72
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: runeterra_cards
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James "zofrex" Sanderson
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: base32
|
@@ -80,20 +80,34 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 1.4.2
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: mutant
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.10.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.10.0
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: mutant-minitest
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
|
-
- - "
|
101
|
+
- - "~>"
|
88
102
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
103
|
+
version: 0.10.0
|
90
104
|
type: :development
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
|
-
- - "
|
108
|
+
- - "~>"
|
95
109
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
110
|
+
version: 0.10.0
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: rake
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,14 +128,14 @@ dependencies:
|
|
114
128
|
requirements:
|
115
129
|
- - "~>"
|
116
130
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
131
|
+
version: '1.2'
|
118
132
|
type: :development
|
119
133
|
prerelease: false
|
120
134
|
version_requirements: !ruby/object:Gem::Requirement
|
121
135
|
requirements:
|
122
136
|
- - "~>"
|
123
137
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
138
|
+
version: '1.2'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: rubocop-minitest
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,28 +156,28 @@ dependencies:
|
|
142
156
|
requirements:
|
143
157
|
- - "~>"
|
144
158
|
- !ruby/object:Gem::Version
|
145
|
-
version: 0.
|
159
|
+
version: 0.5.1
|
146
160
|
type: :development
|
147
161
|
prerelease: false
|
148
162
|
version_requirements: !ruby/object:Gem::Requirement
|
149
163
|
requirements:
|
150
164
|
- - "~>"
|
151
165
|
- !ruby/object:Gem::Version
|
152
|
-
version: 0.
|
166
|
+
version: 0.5.1
|
153
167
|
- !ruby/object:Gem::Dependency
|
154
168
|
name: rubocop-performance
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
156
170
|
requirements:
|
157
171
|
- - "~>"
|
158
172
|
- !ruby/object:Gem::Version
|
159
|
-
version: '1.
|
173
|
+
version: '1.8'
|
160
174
|
type: :development
|
161
175
|
prerelease: false
|
162
176
|
version_requirements: !ruby/object:Gem::Requirement
|
163
177
|
requirements:
|
164
178
|
- - "~>"
|
165
179
|
- !ruby/object:Gem::Version
|
166
|
-
version: '1.
|
180
|
+
version: '1.8'
|
167
181
|
- !ruby/object:Gem::Dependency
|
168
182
|
name: yard
|
169
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -189,23 +203,24 @@ files:
|
|
189
203
|
- LICENSE.txt
|
190
204
|
- doc/CHANGELOG.md
|
191
205
|
- doc/README.md
|
192
|
-
- doc/version_helper.rb
|
193
206
|
- lib/runeterra_cards.rb
|
194
|
-
- lib/runeterra_cards/
|
207
|
+
- lib/runeterra_cards/card.rb
|
195
208
|
- lib/runeterra_cards/card_metadata.rb
|
196
209
|
- lib/runeterra_cards/card_set.rb
|
210
|
+
- lib/runeterra_cards/cost.rb
|
197
211
|
- lib/runeterra_cards/errors.rb
|
198
212
|
- lib/runeterra_cards/factions.rb
|
199
213
|
- lib/runeterra_cards/metadata.rb
|
200
214
|
- lib/runeterra_cards/version.rb
|
201
|
-
homepage:
|
215
|
+
homepage:
|
202
216
|
licenses:
|
203
217
|
- MIT
|
204
218
|
metadata:
|
205
219
|
bug_tracker_uri: https://github.com/zofrex/runeterra_cards/issues
|
206
|
-
changelog_uri: https://www.rubydoc.info/gems/runeterra_cards/doc/CHANGELOG.md
|
220
|
+
changelog_uri: https://www.rubydoc.info/gems/runeterra_cards/file/doc/CHANGELOG.md
|
207
221
|
source_code_uri: https://github.com/zofrex/runeterra_cards
|
208
|
-
|
222
|
+
documentation_uri: https://www.rubydoc.info/gems/runeterra_cards/
|
223
|
+
post_install_message:
|
209
224
|
rdoc_options: []
|
210
225
|
require_paths:
|
211
226
|
- lib
|
@@ -221,7 +236,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
221
236
|
version: '0'
|
222
237
|
requirements: []
|
223
238
|
rubygems_version: 3.1.4
|
224
|
-
signing_key:
|
239
|
+
signing_key:
|
225
240
|
specification_version: 4
|
226
241
|
summary: Legends of Runeterra deck code decoder & Data Dragon card data loader.
|
227
242
|
test_files: []
|
data/doc/version_helper.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'yard'
|
4
|
-
require 'runeterra_cards/version'
|
5
|
-
|
6
|
-
# Convert `{version}` in markup files to the latest version of the library, i.e. {RuneterraCards::VERSION}
|
7
|
-
module VersionHelper
|
8
|
-
def resolve_links(text)
|
9
|
-
text = text.gsub(/{version}/, RuneterraCards::VERSION)
|
10
|
-
super(text)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
YARD::Templates::Template.extra_includes << VersionHelper
|