hearthstone 0.2.0 → 0.3.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/lib/hearthstone/log/data/game.rb +6 -0
- data/lib/hearthstone/log/game_logger.rb +3 -3
- data/lib/hearthstone/log/parser.rb +42 -42
- data/lib/hearthstone/version.rb +1 -1
- data/spec/hearthstone/log/game_spec.rb +12 -0
- data/spec/hearthstone/log/parser_spec.rb +23 -23
- metadata +4 -16
- data/lib/hearthstone/models.rb +0 -3
- data/lib/hearthstone/models/AllSetsAllLanguages.json +0 -1
- data/lib/hearthstone/models/card.rb +0 -20
- data/lib/hearthstone/models/card_store.rb +0 -50
- data/lib/hearthstone/models/entity.rb +0 -67
- data/lib/hearthstone/models/game.rb +0 -151
- data/lib/hearthstone/models/game_loader.rb +0 -52
- data/lib/hearthstone/models/player.rb +0 -37
- data/spec/hearthstone/models/card_store_spec.rb +0 -16
- data/spec/hearthstone/models/game_loader_spec.rb +0 -153
- data/spec/hearthstone/models/game_spec.rb +0 -157
@@ -1,20 +0,0 @@
|
|
1
|
-
module Hearthstone
|
2
|
-
module Models
|
3
|
-
class Card
|
4
|
-
attr_accessor :name, :cost, :type, :rarity, :faction, :text, :mechanics, :flavor
|
5
|
-
attr_accessor :artist, :attack, :health, :collectible, :id, :elite
|
6
|
-
|
7
|
-
def eql?(other)
|
8
|
-
other.equal?(id) || id == other.id
|
9
|
-
end
|
10
|
-
|
11
|
-
def hash
|
12
|
-
id.hash
|
13
|
-
end
|
14
|
-
|
15
|
-
def to_s
|
16
|
-
"<Card \"#{name}\">"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require_relative './card'
|
3
|
-
|
4
|
-
module Hearthstone
|
5
|
-
module Models
|
6
|
-
class CardStore
|
7
|
-
STORE_FILE = "./AllSetsAllLanguages.json"
|
8
|
-
|
9
|
-
attr_reader :cards
|
10
|
-
|
11
|
-
def initialize(lang="enUS")
|
12
|
-
filename = File.join(File.dirname(__FILE__), STORE_FILE)
|
13
|
-
config = JSON(File.read(filename))
|
14
|
-
@cards = {}
|
15
|
-
|
16
|
-
if config[lang]
|
17
|
-
config[lang].each do |set, cards_data|
|
18
|
-
cards_data.each do |data|
|
19
|
-
card = Card.new
|
20
|
-
card.name = data["name"]
|
21
|
-
card.cost = data["cost"]
|
22
|
-
card.type = data["type"]
|
23
|
-
|
24
|
-
card.rarity = data["rarity"]
|
25
|
-
card.faction = data["faction"]
|
26
|
-
card.text = data["text"]
|
27
|
-
card.mechanics = data["mechanics"]
|
28
|
-
|
29
|
-
card.flavor = data["flavor"]
|
30
|
-
card.artist = data["artist"]
|
31
|
-
card.attack = data["attack"]
|
32
|
-
card.health = data["health"]
|
33
|
-
card.collectible = data["collectible"]
|
34
|
-
card.id = data["id"]
|
35
|
-
card.elite = data["elite"]
|
36
|
-
|
37
|
-
@cards[card.id] = card
|
38
|
-
end
|
39
|
-
end
|
40
|
-
else
|
41
|
-
raise "language '#{lang}'' not found!"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def card_with_id(id)
|
46
|
-
@cards[id]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,67 +0,0 @@
|
|
1
|
-
module Hearthstone
|
2
|
-
module Models
|
3
|
-
# represent an object in game
|
4
|
-
class Entity
|
5
|
-
attr_accessor :id, :card, :damaged
|
6
|
-
attr_reader :attachments
|
7
|
-
|
8
|
-
def initialize(id: nil, card: nil)
|
9
|
-
@id = id
|
10
|
-
@card = card
|
11
|
-
@damaged = 0
|
12
|
-
@attachments = []
|
13
|
-
end
|
14
|
-
|
15
|
-
def eql?(other)
|
16
|
-
other.equal?(id) || id == other.id
|
17
|
-
end
|
18
|
-
|
19
|
-
def hash
|
20
|
-
id.hash
|
21
|
-
end
|
22
|
-
|
23
|
-
def attach(card)
|
24
|
-
attachments << card
|
25
|
-
end
|
26
|
-
|
27
|
-
def detach(card)
|
28
|
-
attachments.delete(card)
|
29
|
-
end
|
30
|
-
|
31
|
-
def current_health
|
32
|
-
if self.card
|
33
|
-
[0, self.card.health - damaged].max
|
34
|
-
else
|
35
|
-
0
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def attack
|
40
|
-
self.card.attack
|
41
|
-
end
|
42
|
-
|
43
|
-
def name
|
44
|
-
card.name
|
45
|
-
end
|
46
|
-
|
47
|
-
def to_s
|
48
|
-
attachment_names = attachments.collect(&:name)
|
49
|
-
attachment_str = ""
|
50
|
-
if attachment_names.count > 0
|
51
|
-
attachment_str = attachment_names.join(", ")
|
52
|
-
end
|
53
|
-
|
54
|
-
if card
|
55
|
-
case card.type
|
56
|
-
when "Minion"
|
57
|
-
"##{id} #{card.name} (#{attack}/#{current_health}) #{attachment_str}"
|
58
|
-
else
|
59
|
-
"##{id} #{card.name}"
|
60
|
-
end
|
61
|
-
else
|
62
|
-
"##{id} Hidden"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
@@ -1,151 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'set'
|
3
|
-
|
4
|
-
require_relative './card_store'
|
5
|
-
require_relative './entity'
|
6
|
-
require_relative './player'
|
7
|
-
|
8
|
-
module Hearthstone
|
9
|
-
module Models
|
10
|
-
class Game
|
11
|
-
attr_reader :store, :entities, :players
|
12
|
-
attr_accessor :turn
|
13
|
-
|
14
|
-
def initialize(store=CardStore.new)
|
15
|
-
@store = store
|
16
|
-
@entities = {}
|
17
|
-
@players = []
|
18
|
-
end
|
19
|
-
|
20
|
-
## Events
|
21
|
-
|
22
|
-
def add_player(id: nil, name: nil, first_player: nil, hero_id: nil, hero_card_id: nil, hero_power_id: nil, hero_power_card_id: nil)
|
23
|
-
hero = entity_with_id(hero_id, card_id: hero_card_id)
|
24
|
-
hero_power = entity_with_id(hero_power_id, card_id: hero_power_card_id)
|
25
|
-
player = Player.new(id: id, name: name, first_player: first_player, hero: hero, hero_power: hero_power)
|
26
|
-
self.players << player
|
27
|
-
end
|
28
|
-
|
29
|
-
def open_card(id: nil, card_id: nil)
|
30
|
-
entity_with_id(id).card = card_with_card_id(card_id)
|
31
|
-
end
|
32
|
-
|
33
|
-
def card_revealed(id: nil, card_id: nil, player_id: nil)
|
34
|
-
entity_with_id(id).card = card_with_card_id(card_id)
|
35
|
-
end
|
36
|
-
|
37
|
-
def card_added_to_deck(player_id: nil, id: nil, card_id: nil)
|
38
|
-
entity = entity_with_id(id, card_id: card_id)
|
39
|
-
entity.card = card_with_card_id(card_id)
|
40
|
-
player = player_with_id(player_id)
|
41
|
-
raise "Player #{player_id} not found!" unless player
|
42
|
-
|
43
|
-
player.move_card(entity, :deck)
|
44
|
-
end
|
45
|
-
|
46
|
-
def card_received(player_id: nil, id: nil, card_id: nil)
|
47
|
-
entity = entity_with_id(id, card_id: card_id)
|
48
|
-
entity.card = card_with_card_id(card_id)
|
49
|
-
player = player_with_id(player_id)
|
50
|
-
raise "Player #{player_id} not found!" unless player
|
51
|
-
|
52
|
-
player.move_card(entity, :hand)
|
53
|
-
end
|
54
|
-
|
55
|
-
def card_drawn(player_id: nil, id: nil, card_id: nil)
|
56
|
-
entity = entity_with_id(id, card_id: card_id)
|
57
|
-
entity.card = card_with_card_id(card_id)
|
58
|
-
player = player_with_id(player_id)
|
59
|
-
raise "Player #{player_id} not found!" unless player
|
60
|
-
|
61
|
-
player.move_card(entity, :hand)
|
62
|
-
end
|
63
|
-
|
64
|
-
def card_attached(attachment_id: nil, target_id: nil)
|
65
|
-
target = entity_with_id(target_id)
|
66
|
-
attachment = entity_with_id(attachment_id)
|
67
|
-
target.attach(attachment)
|
68
|
-
end
|
69
|
-
|
70
|
-
def apply_damage(id: nil, amount: 0, card_id: nil, player_id: nil)
|
71
|
-
target = entity_with_id(id)
|
72
|
-
target.damaged = amount
|
73
|
-
end
|
74
|
-
alias_method :damage, :apply_damage
|
75
|
-
|
76
|
-
def card_played(player_id: nil, id: nil, card_id: nil)
|
77
|
-
player = player_with_id(player_id)
|
78
|
-
target = entity_with_id(id)
|
79
|
-
target.card = card_with_card_id(card_id)
|
80
|
-
raise "Player #{player_id} not found!" unless player
|
81
|
-
#binding.pry
|
82
|
-
|
83
|
-
player.move_card(target, :play)
|
84
|
-
end
|
85
|
-
|
86
|
-
def card_destroyed(player_id: nil, id: nil, card_id: nil)
|
87
|
-
player = player_with_id(player_id)
|
88
|
-
target = entity_with_id(id)
|
89
|
-
raise "Player #{player_id} not found!" unless player
|
90
|
-
|
91
|
-
player.move_card(target, :graveyard)
|
92
|
-
end
|
93
|
-
alias_method :card_discarded, :card_destroyed
|
94
|
-
|
95
|
-
def card_put_in_play(player_id: nil, id: nil, card_id: nil)
|
96
|
-
entity = entity_with_id(id, card_id: card_id)
|
97
|
-
entity.card = card_with_card_id(card_id)
|
98
|
-
player = player_with_id(player_id)
|
99
|
-
raise "Player #{player_id} not found!" unless player
|
100
|
-
|
101
|
-
player.move_card(entity, :play)
|
102
|
-
end
|
103
|
-
|
104
|
-
## Accessors
|
105
|
-
|
106
|
-
def entity_with_id(id, card_id: nil)
|
107
|
-
entity = entities[id]
|
108
|
-
unless entity
|
109
|
-
entity = Entity.new(id: id, card: card_with_card_id(card_id))
|
110
|
-
entities[id] = entity
|
111
|
-
end
|
112
|
-
entity
|
113
|
-
end
|
114
|
-
|
115
|
-
def player_with_id(id)
|
116
|
-
self.players.detect{|p| p.id == id}
|
117
|
-
end
|
118
|
-
|
119
|
-
def card_with_card_id(card_id)
|
120
|
-
card = nil
|
121
|
-
if card_id && card_id != ""
|
122
|
-
card = self.store.card_with_id(card_id)
|
123
|
-
raise "Card #{card_id} not found!" unless card
|
124
|
-
end
|
125
|
-
card
|
126
|
-
end
|
127
|
-
|
128
|
-
## Public
|
129
|
-
|
130
|
-
def to_s
|
131
|
-
player1 = self.players.first
|
132
|
-
player2 = self.players.last
|
133
|
-
|
134
|
-
"""======================= Turn ##{turn} =====================
|
135
|
-
#{player1.name} (#{player1.hero.current_health})
|
136
|
-
======================================================
|
137
|
-
|
138
|
-
#{player1.play.collect(&:to_s).join("\n")}
|
139
|
-
|
140
|
-
----------------------------------------------------
|
141
|
-
|
142
|
-
#{player2.play.collect(&:to_s).join("\n")}
|
143
|
-
|
144
|
-
======================================================
|
145
|
-
#{player2.name} (#{player2.hero.current_health})
|
146
|
-
======================================================
|
147
|
-
"""
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
|
3
|
-
require_relative './game'
|
4
|
-
|
5
|
-
module Hearthstone
|
6
|
-
module Models
|
7
|
-
class GameLoader
|
8
|
-
attr_accessor :data
|
9
|
-
attr_reader :game
|
10
|
-
|
11
|
-
def initialize(data)
|
12
|
-
@data = data
|
13
|
-
@game = Game.new
|
14
|
-
end
|
15
|
-
|
16
|
-
def load_players
|
17
|
-
data[:players].each do |player|
|
18
|
-
game.add_player(id: player[:id], name: player[:name], first_player: player[:first_player],
|
19
|
-
hero_id: player[:hero][:id], hero_card_id: player[:hero][:card_id],
|
20
|
-
hero_power_id: player[:hero_power][:id], hero_power_card_id: player[:hero_power][:card_id])
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def load_turns
|
25
|
-
data[:turns].each do |turn|
|
26
|
-
load_turn(number: turn[:number], events: turn[:events])
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def load_turn(number: 0, events: [])
|
31
|
-
game.turn = number
|
32
|
-
|
33
|
-
events.each do |event|
|
34
|
-
load_event(event[0], event[1])
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def load_event(name, data)
|
39
|
-
event_sym = name.to_sym
|
40
|
-
case event_sym
|
41
|
-
when :open_card, :card_received, :card_revealed, :card_played, :card_added_to_deck, :card_drawn, :card_discarded, :card_destroyed, :card_put_in_play
|
42
|
-
game.send(event_sym, data)
|
43
|
-
when :damaged
|
44
|
-
game.apply_damage(id: data[:id], amount: data[:amount])
|
45
|
-
when :attached
|
46
|
-
game.card_attached(attachment_id: data[:id], target_id: data[:target])
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
module Hearthstone
|
2
|
-
module Models
|
3
|
-
class Player
|
4
|
-
attr_reader :id, :name, :first_player
|
5
|
-
attr_accessor :hero, :hero_power
|
6
|
-
attr_reader :deck, :hand, :play, :graveyard, :setaside
|
7
|
-
|
8
|
-
def initialize(id: nil, name: nil, first_player: nil, hero: nil, hero_power: nil)
|
9
|
-
@id = id
|
10
|
-
@name = name
|
11
|
-
@first_player = first_player
|
12
|
-
@hero = hero
|
13
|
-
@hero_power = hero_power
|
14
|
-
|
15
|
-
@deck = Set.new
|
16
|
-
@hand = Set.new
|
17
|
-
@play = Set.new
|
18
|
-
@graveyard = Set.new
|
19
|
-
@setaside = Set.new
|
20
|
-
end
|
21
|
-
|
22
|
-
def move_card(card, to_zone)
|
23
|
-
[:deck, :hand, :play, :graveyard, :setaside].each do |zone|
|
24
|
-
if to_zone != zone
|
25
|
-
self.send(zone).delete(card)
|
26
|
-
else
|
27
|
-
self.send(to_zone) << card
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_s
|
33
|
-
"<Player ##{id} \"#{name}\">"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
require_relative "../../../lib/hearthstone/models"
|
2
|
-
|
3
|
-
|
4
|
-
describe Hearthstone::Models::CardStore do
|
5
|
-
let(:store) { Hearthstone::Models::CardStore.new }
|
6
|
-
|
7
|
-
context "#card_with_id" do
|
8
|
-
it "returns the card with specific id" do
|
9
|
-
jenkins = store.card_with_id("EX1_116")
|
10
|
-
expect(jenkins.name).to eq("Leeroy Jenkins")
|
11
|
-
|
12
|
-
jenkins2 = store.card_with_id("EX1_116")
|
13
|
-
expect(jenkins2).to eq(jenkins)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,153 +0,0 @@
|
|
1
|
-
require_relative "../../../lib/hearthstone/models"
|
2
|
-
require 'json'
|
3
|
-
|
4
|
-
describe Hearthstone::Models::GameLoader do
|
5
|
-
before(:all) {
|
6
|
-
filename = File.join(File.dirname(__FILE__), "../../fixtures/game1.json")
|
7
|
-
@data = JSON.parse(open(filename).read, symbolize_names: true)
|
8
|
-
}
|
9
|
-
|
10
|
-
context "#load_players" do
|
11
|
-
it "should load players" do
|
12
|
-
loader = Hearthstone::Models::GameLoader.new(@data)
|
13
|
-
loader.load_players
|
14
|
-
|
15
|
-
game = loader.game
|
16
|
-
expect(game.players.count).to eq(2)
|
17
|
-
|
18
|
-
first = game.players.first
|
19
|
-
expect(first.name).to eq("ALzard")
|
20
|
-
expect(first.hero.name).to eq("Thrall")
|
21
|
-
|
22
|
-
last = game.players.last
|
23
|
-
expect(last.name).to eq("siuying")
|
24
|
-
expect(last.hero.name).to eq("Rexxar")
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
context "Load Games" do
|
29
|
-
before(:each) do
|
30
|
-
@loader = Hearthstone::Models::GameLoader.new(@data)
|
31
|
-
@loader.load_players
|
32
|
-
@game = @loader.game
|
33
|
-
end
|
34
|
-
|
35
|
-
context "#load_event" do
|
36
|
-
it "should load open card event" do
|
37
|
-
@loader.load_event(:open_card, id: 5, card_id: "CS2_101")
|
38
|
-
|
39
|
-
entity = @game.entity_with_id(5)
|
40
|
-
expect(entity.card.id).to eq("CS2_101")
|
41
|
-
end
|
42
|
-
|
43
|
-
it "should load card received event" do
|
44
|
-
@loader.load_event(:card_received, player_id: 2, id: 7, card_id: "CS2_101")
|
45
|
-
|
46
|
-
entity = @game.entity_with_id(7)
|
47
|
-
expect(entity.card.id).to eq("CS2_101")
|
48
|
-
|
49
|
-
player = @game.player_with_id(2)
|
50
|
-
expect(player.hand).to include(entity)
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should load card reveal event" do
|
54
|
-
@loader.load_event(:open_card, id: 7, card_id: "")
|
55
|
-
@loader.load_event(:card_revealed, id: 7, card_id: "CS2_101")
|
56
|
-
|
57
|
-
entity = @game.entity_with_id(7)
|
58
|
-
expect(entity.card.id).to eq("CS2_101")
|
59
|
-
end
|
60
|
-
|
61
|
-
it "should load card_added_to_deck event" do
|
62
|
-
@loader.load_event(:card_added_to_deck, player_id: 2, id: 7, card_id: "")
|
63
|
-
|
64
|
-
entity = @game.entity_with_id(7)
|
65
|
-
expect(entity.card).to be_nil
|
66
|
-
|
67
|
-
player = @game.player_with_id(2)
|
68
|
-
expect(player.deck).to include(entity)
|
69
|
-
end
|
70
|
-
|
71
|
-
it "should handle card_drawn event" do
|
72
|
-
@loader.load_event(:card_drawn, player_id: 2, id: 7, card_id: "CS2_101")
|
73
|
-
|
74
|
-
entity = @game.entity_with_id(7)
|
75
|
-
player = @game.player_with_id(2)
|
76
|
-
expect(player.hand).to include(entity)
|
77
|
-
end
|
78
|
-
|
79
|
-
it "should handle card_destroyed event" do
|
80
|
-
@loader.load_event(:card_destroyed, player_id: 1, id: 26)
|
81
|
-
|
82
|
-
entity = @game.entity_with_id(26)
|
83
|
-
player = @game.player_with_id(1)
|
84
|
-
expect(player.graveyard).to include(entity)
|
85
|
-
end
|
86
|
-
|
87
|
-
it "should handle card_put_in_play event" do
|
88
|
-
@loader.load_event(:card_put_in_play, player_id: 2, id: 7, card_id: "CS2_101")
|
89
|
-
|
90
|
-
entity = @game.entity_with_id(7)
|
91
|
-
player = @game.player_with_id(2)
|
92
|
-
expect(player.play).to include(entity)
|
93
|
-
end
|
94
|
-
|
95
|
-
it "should handle damaged event" do
|
96
|
-
@loader.load_event(:damaged, id: 7, amount: 2)
|
97
|
-
|
98
|
-
entity = @game.entity_with_id(7)
|
99
|
-
expect(entity.damaged).to eq(2)
|
100
|
-
end
|
101
|
-
|
102
|
-
it "should handle attached event" do
|
103
|
-
@loader.load_event(:open_card, id: 7, card_id: "")
|
104
|
-
@loader.load_event(:open_card, id: 26, card_id: "")
|
105
|
-
@loader.load_event(:attached, id: 26, target: 7)
|
106
|
-
|
107
|
-
entity = @game.entity_with_id(7)
|
108
|
-
attachment = @game.entity_with_id(26)
|
109
|
-
expect(entity.attachments).to include(attachment)
|
110
|
-
end
|
111
|
-
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
context "#load_turns" do
|
116
|
-
before(:each) do
|
117
|
-
filename = File.join(File.dirname(__FILE__), "../../fixtures/gamelog1.json")
|
118
|
-
@data = JSON.parse(open(filename).read, symbolize_names: true)
|
119
|
-
@loader = Hearthstone::Models::GameLoader.new(@data)
|
120
|
-
@loader.load_players
|
121
|
-
@game = @loader.game
|
122
|
-
end
|
123
|
-
|
124
|
-
it "should load a game" do
|
125
|
-
@data[:turns].each do |turn|
|
126
|
-
@loader.load_turn(number: turn[:number], events: turn[:events])
|
127
|
-
|
128
|
-
@game.players.each do |player|
|
129
|
-
# deck cards always unknown
|
130
|
-
player.deck.each do |entity|
|
131
|
-
expect(entity.card).to be_nil
|
132
|
-
end
|
133
|
-
|
134
|
-
# graveyard cards always known
|
135
|
-
player.graveyard.each do |entity|
|
136
|
-
expect(entity.card).to_not be_nil
|
137
|
-
end
|
138
|
-
|
139
|
-
# hands cards only known for current player
|
140
|
-
player.hand.each do |entity|
|
141
|
-
if player.name == "siuying"
|
142
|
-
expect(entity.card).to_not be_nil
|
143
|
-
else
|
144
|
-
expect(entity.card).to be_nil
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
end
|