hearthstone 0.2.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.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +43 -0
  6. data/Rakefile +2 -0
  7. data/bin/hearthstone-recorder +7 -0
  8. data/hearthstone.gemspec +28 -0
  9. data/lib/hearthstone.rb +7 -0
  10. data/lib/hearthstone/commands/recorder_command.rb +86 -0
  11. data/lib/hearthstone/log.rb +7 -0
  12. data/lib/hearthstone/log/configurator.rb +41 -0
  13. data/lib/hearthstone/log/data.rb +1 -0
  14. data/lib/hearthstone/log/data/game.rb +74 -0
  15. data/lib/hearthstone/log/data/game_player.rb +25 -0
  16. data/lib/hearthstone/log/data/game_turn.rb +32 -0
  17. data/lib/hearthstone/log/game_logger.rb +128 -0
  18. data/lib/hearthstone/log/parser.rb +276 -0
  19. data/lib/hearthstone/models.rb +3 -0
  20. data/lib/hearthstone/models/AllSetsAllLanguages.json +1 -0
  21. data/lib/hearthstone/models/card.rb +20 -0
  22. data/lib/hearthstone/models/card_store.rb +50 -0
  23. data/lib/hearthstone/models/entity.rb +67 -0
  24. data/lib/hearthstone/models/game.rb +151 -0
  25. data/lib/hearthstone/models/game_loader.rb +52 -0
  26. data/lib/hearthstone/models/player.rb +37 -0
  27. data/lib/hearthstone/version.rb +3 -0
  28. data/spec/fixtures/completed.config +8 -0
  29. data/spec/fixtures/empty_config.config +0 -0
  30. data/spec/fixtures/game1.json +2433 -0
  31. data/spec/fixtures/gamelog1.json +1585 -0
  32. data/spec/fixtures/gamelog1.log +25508 -0
  33. data/spec/fixtures/gamelog2.log +85357 -0
  34. data/spec/hearthstone/log/configurator_spec.rb +61 -0
  35. data/spec/hearthstone/log/game_logger_spec.rb +57 -0
  36. data/spec/hearthstone/log/parser_spec.rb +185 -0
  37. data/spec/hearthstone/models/card_store_spec.rb +16 -0
  38. data/spec/hearthstone/models/game_loader_spec.rb +153 -0
  39. data/spec/hearthstone/models/game_spec.rb +157 -0
  40. metadata +179 -0
@@ -0,0 +1,61 @@
1
+ require_relative "../../../lib/hearthstone"
2
+ require 'tempfile'
3
+
4
+ describe Hearthstone::Log::Configurator do
5
+ context "#needs_config?" do
6
+ it "should needs config for nonexisted config file" do
7
+ filename = File.join(File.dirname(__FILE__), "../../fixtures/not_found")
8
+ subject = Hearthstone::Log::Configurator.new(filename)
9
+ expect(subject.needs_config?).to eq(true)
10
+ end
11
+
12
+ it "should needs config for incompleted config file" do
13
+ filename = File.join(File.dirname(__FILE__), "../../fixtures/empty_config.config")
14
+ subject = Hearthstone::Log::Configurator.new(filename)
15
+ expect(subject.needs_config?).to eq(true)
16
+ end
17
+
18
+ it "should not need config for completed config file" do
19
+ filename = File.join(File.dirname(__FILE__), "../../fixtures/completed.config")
20
+ subject = Hearthstone::Log::Configurator.new(filename)
21
+ expect(subject.needs_config?).to eq(false)
22
+ end
23
+ end
24
+
25
+ context "#configure" do
26
+ before(:each) do
27
+ @file = Tempfile.new("configurator")
28
+ end
29
+
30
+ after(:each) do
31
+ @file.close
32
+ end
33
+
34
+ it "write configuration file" do
35
+ subject = Hearthstone::Log::Configurator.new(@file.path)
36
+ subject.configure
37
+
38
+ data = @file.read
39
+ expect(data).to match(/\[Zone\]/)
40
+ expect(data).to match(/\[Power\]/)
41
+ end
42
+
43
+ it "append configuration file" do
44
+ File.open(@file.path, 'w') do |f|
45
+ config = """[Hello]
46
+ foo=bar
47
+ """
48
+ f.write(config)
49
+ end
50
+
51
+ subject = Hearthstone::Log::Configurator.new(@file.path)
52
+ subject.configure
53
+
54
+ data = @file.read
55
+ expect(data).to match(/\[Zone\]/)
56
+ expect(data).to match(/\[Power\]/)
57
+ expect(data).to match(/\[Hello\]/)
58
+ expect(data).to match(/foo=bar/)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,57 @@
1
+ require_relative "../../../lib/hearthstone"
2
+
3
+ require 'pry'
4
+
5
+ describe Hearthstone::Log::GameLogger do
6
+ let(:delegate) { double(:delegate) }
7
+ let(:subject) { Hearthstone::Log::GameLogger.new(delegate) }
8
+
9
+ context "#log_file" do
10
+ it "parse basic game info" do
11
+ filename = File.join(File.dirname(__FILE__), "../../fixtures/gamelog1.log")
12
+ File.open(filename) do |file|
13
+ expect(delegate).to receive(:on_game_over) do |game|
14
+ expect(game.players.count).to eq(2)
15
+
16
+ zardeine = game.players[0]
17
+ expect(zardeine).to_not be_nil
18
+ expect(zardeine.first_player).to eq(false)
19
+
20
+ siuying = game.players[1]
21
+ expect(siuying).to_not be_nil
22
+ expect(siuying.first_player).to eq(true)
23
+
24
+ expect(game.mode).to eq(:ranked)
25
+ expect(game.completed?).to eq(true)
26
+ expect(game.turns.count).to eq(12)
27
+ expect(game.turns.first.number).to eq(0)
28
+ expect(game.turns.last.number).to eq(11)
29
+ end
30
+
31
+ log = file.read
32
+ subject.log_file(log)
33
+ end
34
+ end
35
+
36
+ it "parse log file #2" do
37
+ filename = File.join(File.dirname(__FILE__), "../../fixtures/gamelog2.log")
38
+ File.open(filename) do |file|
39
+ games = []
40
+ expect(delegate).to receive(:on_game_over).twice do |game|
41
+ games << game
42
+ end
43
+
44
+ log = file.read
45
+ subject.log_file(log)
46
+
47
+ game = games.last
48
+ expect(game.mode).to eq(:ranked)
49
+ expect(game.players.count).to eq(2)
50
+ expect(game.completed?).to eq(true)
51
+ expect(game.turns.count).to eq(25)
52
+ expect(game.turns.first.number).to eq(0)
53
+ expect(game.turns.last.number).to eq(24)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,185 @@
1
+ require_relative "../../../lib/hearthstone"
2
+
3
+ describe Hearthstone::Log::Parser, "#parse_line" do
4
+ let (:parser) { Hearthstone::Log::Parser.new }
5
+ it "returns startup on app start" do
6
+ result = parser.parse_line("Initialize engine version: 4.5.5p3 (b8dc95101aa8)")
7
+ expect(result).to eq([:startup])
8
+ end
9
+
10
+ it "returns choice" do
11
+ result = parser.parse_line("[Power] GameState.SendChoices() - id=3 ChoiceType=GENERAL")
12
+ expect(result).to eq([:choice_type, "GENERAL"])
13
+
14
+ result = parser.parse_line("[Power] GameState.SendChoices() - m_chosenEntities[0]=[name=Feign Death id=38 zone=HAND zonePos=3 cardId=GVG_026 player=2]")
15
+ expect(result).to eq([:choose, id: 38, card_id: 'GVG_026', player_id: 2])
16
+
17
+ result = parser.parse_line("[Power] GameState.SendChoices() - m_chosenEntities[0]=[name=Undertaker id=8 zone=SETASIDE zonePos=0 cardId=FP1_028 player=1]")
18
+ expect(result).to eq([:choose, id: 8, card_id: 'FP1_028', player_id: 1])
19
+ end
20
+
21
+ it "returns spectator mode" do
22
+ result = parser.parse_line("[Power] Begin Spectating")
23
+ expect(result).to eq([:begin_spectator_mode])
24
+
25
+ result = parser.parse_line("[Power] End Spectator Mode")
26
+ expect(result).to eq([:end_spectator_mode])
27
+ end
28
+
29
+ it "returns arena and ranked mode" do
30
+ result = parser.parse_line("[LoadingScreen] LoadingScreen.OnSceneLoaded() - prevMode=HUB currMode=DRAFT")
31
+ expect(result).to eq([:mode, :arena])
32
+
33
+ result = parser.parse_line("[LoadingScreen] LoadingScreen.OnSceneLoaded() - prevMode=GAMEPLAY currMode=TOURNAMENT")
34
+ expect(result).to eq([:mode, :ranked])
35
+
36
+ result = parser.parse_line("[LoadingScreen] LoadingScreen.OnSceneLoaded() - prevMode=HUB currMode=ADVENTURE")
37
+ expect(result).to eq([:mode, :solo])
38
+ end
39
+
40
+ it "returns action start" do
41
+ result = parser.parse_line("[Power] GameState.DebugPrintPower() - ACTION_START Entity=[name=Undertaker id=59 zone=PLAY zonePos=1 cardId=FP1_028 player=2] SubType=ATTACK Index=-1 Target=[name=Rexxar id=4 zone=PLAY zonePos=0 cardId=HERO_05 player=1]")
42
+ expect(result).to eq([:action_start, {:subtype=>"ATTACK", :from=>{:id=>59, :card_id=>"FP1_028", :player_id=>2}, :to=>{:id=>4, :card_id=>"HERO_05", :player_id=>1}}])
43
+ end
44
+
45
+ it "returns player state change" do
46
+ result = parser.parse_line("[Power] GameState.DebugPrintPower() - TAG_CHANGE Entity=siuying tag=PLAYER_ID value=2")
47
+ expect(result).to eq([:player_id, name: "siuying", player_id: 2])
48
+
49
+ result = parser.parse_line("[Power] GameState.DebugPrintPower() - TAG_CHANGE Entity=begize tag=FIRST_PLAYER value=1")
50
+ expect(result).to eq([:first_player, name: "begize"])
51
+
52
+ result = parser.parse_line("[Power] GameState.DebugPrintPower() - TAG_CHANGE Entity=begize tag=PLAYSTATE value=WON")
53
+ expect(result).to eq([:game_over, name: "begize", state: "WON"])
54
+
55
+ result = parser.parse_line("[Power] GameState.DebugPrintPower() - TAG_CHANGE Entity=siuying tag=TURN_START value=1418309639")
56
+ expect(result).to eq([:turn_start, name: "siuying", timestamp: 1418309639])
57
+
58
+ result = parser.parse_line("[Power] GameState.DebugPrintPower() - TAG_CHANGE Entity=GameEntity tag=TURN value=3")
59
+ expect(result).to eq([:turn, 3])
60
+
61
+ result = parser.parse_line("[Power] GameState.DebugPrintPower() - TAG_CHANGE Entity=GameEntity tag=TURN_START value=1418310864")
62
+ expect(result).to eq([:game_start])
63
+ end
64
+
65
+ it "returns entity state change" do
66
+ result = parser.parse_line("[Power] GameState.DebugPrintPower() - TAG_CHANGE Entity=[name=Silver Hand Recruit id=71 zone=PLAY zonePos=1 cardId=CS2_101t player=1] tag=DAMAGE value=2
67
+ ")
68
+ expect(result).to eq([:damaged, id: 71, card_id: "CS2_101t", player_id: 1, amount: 2])
69
+
70
+ result = parser.parse_line("[Power] GameState.DebugPrintPower() - TAG_CHANGE Entity=[name=Uther Lightbringer id=4 zone=PLAY zonePos=0 cardId=HERO_04 player=1] tag=ATTACKING value=1")
71
+ expect(result).to eq([:attack, id: 4, card_id: "HERO_04", player_id: 1])
72
+
73
+ result = parser.parse_line("[Power] GameState.DebugPrintPower() - TAG_CHANGE Entity=[name=Rexxar id=36 zone=PLAY zonePos=0 cardId=HERO_05 player=2] tag=DEFENDING value=1")
74
+ expect(result).to eq([:attacked, id: 36, card_id: "HERO_05", player_id: 2])
75
+
76
+ result = parser.parse_line("[Power] GameState.DebugPrintPower() - TAG_CHANGE Entity=[name=Fireblast id=37 zone=PLAY zonePos=0 cardId=CS2_034 player=2] tag=CARD_TARGET value=9")
77
+ expect(result).to eq([:card_target, id: 37, card_id: 'CS2_034', player_id: 2, target: 9])
78
+ end
79
+
80
+ context "returns process change" do
81
+ it "handles hands" do
82
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=47 local=False [name=Reversing Switch id=72 zone=HAND zonePos=7 cardId=PART_006 player=1] zone from -> FRIENDLY HAND"
83
+ result = parser.parse_line(line)
84
+ expect(result).to eq([:card_received, player_id: 1, id: 72, card_id: "PART_006"])
85
+
86
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=1 local=False [id=22 cardId= type=INVALID zone=HAND zonePos=4 player=1] zone from -> OPPOSING HAND"
87
+ result = parser.parse_line(line)
88
+ expect(result).to eq([:card_received, player_id: 1, id: 22, card_id: ""])
89
+
90
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=16 local=False [id=57 cardId= type=INVALID zone=HAND zonePos=0 player=2] zone from OPPOSING DECK -> OPPOSING HAND"
91
+ result = parser.parse_line(line)
92
+ expect(result).to eq([:card_drawn, player_id: 2, id: 57, card_id: ""])
93
+
94
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=27 local=False [name=Boulderfist Ogre id=10 zone=HAND zonePos=0 cardId=CS2_200 player=1] zone from FRIENDLY DECK -> FRIENDLY HAND"
95
+ result = parser.parse_line(line)
96
+ expect(result).to eq([:card_drawn, player_id: 1, id: 10, card_id: 'CS2_200'])
97
+
98
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=20 local=False [name=Leper Gnome id=26 zone=HAND zonePos=2 cardId=EX1_029 player=1] zone from OPPOSING PLAY -> OPPOSING HAND"
99
+ result = parser.parse_line(line)
100
+ expect(result).to eq([:card_returned, player_id: 1, id: 26, card_id: 'EX1_029'])
101
+
102
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=45 local=False [name=Harvest Golem id=10 zone=HAND zonePos=1 cardId=EX1_556 player=1] zone from FRIENDLY PLAY -> FRIENDLY HAND"
103
+ result = parser.parse_line(line)
104
+ expect(result).to eq([:card_returned, player_id: 1, id: 10, card_id: 'EX1_556'])
105
+ end
106
+
107
+ it "handles play" do
108
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=1 local=True [name=Loot Hoarder id=57 zone=HAND zonePos=2 cardId=EX1_096 player=2] zone from FRIENDLY HAND -> FRIENDLY PLAY"
109
+ result = parser.parse_line(line)
110
+ expect(result).to eq([:card_played, player_id: 2, id: 57, card_id: 'EX1_096'])
111
+
112
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=8 local=False [name=Pint-Sized Summoner id=34 zone=PLAY zonePos=1 cardId=EX1_076 player=1] zone from OPPOSING HAND -> OPPOSING PLAY"
113
+ result = parser.parse_line(line)
114
+ expect(result).to eq([:card_played, player_id: 1, id: 34, card_id: 'EX1_076'])
115
+
116
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=84 local=False [name=Ashbringer id=84 zone=PLAY zonePos=0 cardId=EX1_383t player=1] zone from -> OPPOSING PLAY (Weapon)"
117
+ result = parser.parse_line(line)
118
+ expect(result).to eq([:card_put_in_play, player_id: 1, id: 84, card_id: 'EX1_383t'])
119
+
120
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=1 local=False [name=Jaina Proudmoore id=4 zone=PLAY zonePos=0 cardId=HERO_08 player=1] zone from -> FRIENDLY PLAY (Hero)"
121
+ result = parser.parse_line(line)
122
+ expect(result).to eq([:set_hero, player_id: 1, id: 4, card_id: 'HERO_08'])
123
+
124
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=1 local=False [name=Gul'dan id=36 zone=PLAY zonePos=0 cardId=HERO_07 player=2] zone from -> OPPOSING PLAY (Hero)"
125
+ result = parser.parse_line(line)
126
+ expect(result).to eq([:set_hero, player_id: 2, id: 36, card_id: 'HERO_07'])
127
+
128
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=1 local=False [name=Steady Shot id=5 zone=PLAY zonePos=0 cardId=DS1h_292 player=1] zone from -> FRIENDLY PLAY (Hero Power)"
129
+ result = parser.parse_line(line)
130
+ expect(result).to eq([:set_hero_power, player_id: 1, id: 5, card_id: 'DS1h_292'])
131
+
132
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=1 local=False [name=Steady Shot id=37 zone=PLAY zonePos=0 cardId=DS1h_292 player=2] zone from -> OPPOSING PLAY (Hero Power)"
133
+ result = parser.parse_line(line)
134
+ expect(result).to eq([:set_hero_power, player_id: 2, id: 37, card_id: 'DS1h_292'])
135
+ end
136
+
137
+ it "handles deck" do
138
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=2 local=False [name=Sludge Belcher id=46 zone=DECK zonePos=3 cardId=FP1_012 player=2] zone from FRIENDLY HAND -> FRIENDLY DECK"
139
+ result = parser.parse_line(line)
140
+ expect(result).to eq([:card_reshuffled, player_id: 2, id: 46, card_id: "FP1_012"])
141
+
142
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=3 local=False [id=69 cardId= type=INVALID zone=DECK zonePos=2 player=2] zone from OPPOSING HAND -> OPPOSING DECK"
143
+ result = parser.parse_line(line)
144
+ expect(result).to eq([:card_reshuffled, player_id: 2, id: 69, card_id: ""])
145
+
146
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=1 local=False [id=38 cardId= type=INVALID zone=DECK zonePos=0 player=2] zone from -> FRIENDLY DECK"
147
+ result = parser.parse_line(line)
148
+ expect(result).to eq([:card_added_to_deck, player_id: 2, id: 38, card_id: ""])
149
+
150
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=1 local=False [id=6 cardId= type=INVALID zone=DECK zonePos=0 player=1] zone from -> OPPOSING DECK"
151
+ result = parser.parse_line(line)
152
+ expect(result).to eq([:card_added_to_deck, player_id: 1, id: 6, card_id: ""])
153
+ end
154
+
155
+ it "handles graveyard" do
156
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=21 local=False [name=Webspinner id=65 zone=GRAVEYARD zonePos=2 cardId=FP1_011 player=2] zone from FRIENDLY PLAY -> FRIENDLY GRAVEYARD"
157
+ result = parser.parse_line(line)
158
+ expect(result).to eq([:card_destroyed, player_id: 2, id: 65, card_id: "FP1_011"])
159
+
160
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=42 local=False [name=Animal Companion id=50 zone=GRAVEYARD zonePos=0 cardId=NEW1_031 player=2] zone from -> OPPOSING GRAVEYARD"
161
+ result = parser.parse_line(line)
162
+ expect(result).to eq([:card_discarded, player_id: 2, id: 50, card_id: "NEW1_031"])
163
+
164
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=86 local=False [name=Uther Lightbringer id=4 zone=GRAVEYARD zonePos=0 cardId=HERO_04 player=1] zone from OPPOSING PLAY (Hero) -> OPPOSING GRAVEYARD"
165
+ result = parser.parse_line(line)
166
+ expect(result).to eq([:hero_destroyed, player_id: 1, id: 4, card_id: "HERO_04"])
167
+
168
+ end
169
+
170
+ it "handles secrets" do
171
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=80 local=False [id=30 cardId= type=INVALID zone=SECRET zonePos=0 player=1] zone from OPPOSING DECK -> OPPOSING SECRET"
172
+ result = parser.parse_line(line)
173
+ expect(result).to eq([:card_put_in_play, player_id: 1, id: 30, card_id: ''])
174
+
175
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=29 local=False [name=Explosive Trap id=43 zone=SECRET zonePos=0 cardId=EX1_610 player=2] zone from FRIENDLY DECK -> FRIENDLY SECRET"
176
+ result = parser.parse_line(line)
177
+ expect(result).to eq([:card_put_in_play, player_id: 2, id: 43, card_id: 'EX1_610'])
178
+
179
+ line = "[Zone] ZoneChangeList.ProcessChanges() - id=45 local=False [name=Freezing Trap id=66 zone=SETASIDE zonePos=0 cardId=EX1_611 player=2] zone from FRIENDLY DECK -> "
180
+ result = parser.parse_line(line)
181
+ expect(result).to eq([:card_setaside, player_id: 2, id: 66, card_id: 'EX1_611'])
182
+ end
183
+ end
184
+
185
+ end
@@ -0,0 +1,16 @@
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
@@ -0,0 +1,153 @@
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