forked from tobymao/18xx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
validate.rb
198 lines (166 loc) · 5.03 KB
/
validate.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# frozen_string_literal: true
# rubocop:disable all
require 'json'
require_relative 'models'
Dir['./models/**/*.rb'].sort.each { |file| require file }
Sequel.extension :pg_json_ops
require './lib/engine'
load 'migrate_game.rb'
# class to facilitate interacting with the results of validate_all() in an irb
# console
class Validate
attr_reader :filename
def initialize(filename)
@filename = filename
end
def write(filename)
@filename = filename
File.write(filename, JSON.pretty_generate(data))
end
def data
@data ||= JSON.parse(File.read(filename))
end
def ids
@ids ||= data.keys.map(&:to_i)
end
def titles
@titles ||= data.map { |_id, g| g['title'] }.uniq.sort
end
def errors
@errors ||= data.select { |_id, g| g['exception'] }
end
def error_ids
@error_ids ||= errors.keys.map(&:to_i)
end
def error_titles
@error_titles ||= errors.map { |_id, g| g['title'] }.uniq.sort
end
end
$count = 0
$total = 0
$total_time = 0
def run_game(game, actions = nil, strict: false)
actions ||= game.actions.map(&:to_h)
data={'id':game.id, 'title': game.title, 'status':game.status}
$total += 1
time = Time.now
begin
engine = Engine::Game.load(game, strict: strict)
rescue Exception => e # rubocop:disable Lint/RescueException
$count += 1
data['finished']=false
#data['stack']=e.backtrace
data['exception']=e
return data
end
begin
engine.maybe_raise!
time = Time.now - time
$total_time += time
data['finished']=true
data['actions']=engine.actions.size
data['result']=engine.result
rescue Exception => e # rubocop:disable Lint/RescueException
$count += 1
data['url']="https://18xx.games/game/#{game.id}?action=#{engine.last_processed_action}"
data['last_action']=engine.last_processed_action
data['finished']=false
#data['stack']=e.backtrace
data['exception']=e
end
data
end
def validate_all(*titles, game_ids: nil, strict: false, status: %w[active finished], filename: 'validate.json')
$count = 0
$total = 0
$total_time = 0
page = []
data = {}
where_args = {Sequel.pg_jsonb_op(:settings).has_key?('pin') => false, status: status}
where_args[:title] = titles if titles.any?
where_args[:id] = game_ids if game_ids
DB[:games].order(:id).where(**where_args).select(:id).paged_each(rows_per_fetch: 100) do |game|
page << game
if page.size >= 100
where_args2 = {id: page.map { |p| p[:id] }}
where_args2[:title] = titles if titles.any?
games = Game.eager(:user, :players, :actions).where(**where_args2).all
_ = games.each do |game|
data[game.id]=run_game(game, strict: strict)
end
page.clear
end
end
where_args3 = {id: page.map { |p| p[:id] }}
where_args3[:title] = titles if titles.any?
games = Game.eager(:user, :players, :actions).where(**where_args3).all
_ = games.each do |game|
data[game.id]=run_game(game)
end
puts "#{$count}/#{$total} avg #{$total_time / $total}"
data['summary']={'failed':$count, 'total':$total, 'total_time':$total_time, 'avg_time':$total_time / $total}
File.write(filename, JSON.pretty_generate(data))
Validate.new(filename)
end
def validate_one(id)
game = Game[id]
puts run_game(game)
end
def validate_migrated_one_mem(id)
game = Game[id]
puts run_game(game, migrate_db_actions_in_mem(game))
end
def validate_migrated_one(id)
game = Game[id]
puts run_game(game, migrate_db_actions(game))
end
def revalidate_broken(filename)
$count = 0
$total = 0
$total_time = 0
data = JSON.parse(File.read(filename))
data = data.map do |game, val|
if game != 'summary' && !val['finished'] && !val['pin']
reload_game = Game[val['id']]
d = run_game(reload_game, migrate_db_actions(reload_game))
d['original']=val
#[game,run_game(reload_game)]
[game,d]
end
end.compact.to_h
data['updated_summary']={'failed':$count, 'total':$total, 'total_time':$total_time, 'avg_time':$total_time / $total}
File.write("revalidate.json", JSON.pretty_generate(data))
end
def validate_json(filename, strict: false)
game = Engine::Game.load(filename, strict: strict)
if game.exception
puts game.broken_action.to_h
end
game.maybe_raise!
end
def validate_json_auto(filename, strict: false)
# Validate the json, and try and add auto actions at the end
data = JSON.parse(File.read(filename))
rungame = Engine::Game.load(data, strict: strict).maybe_raise!
rungame.maybe_raise!
actions = rungame.class.filtered_actions(data['actions']).first
action = actions.last
# Process game to previous action
auto_game = Engine::Game.load(data, at_action: action['id'] - 1)
# Add the action but without the auto actions
clone = action.dup
clone.delete('auto_actions')
auto_game.process_action(clone, add_auto_actions: true)
auto_game.maybe_raise!
end
def pin_games(pin_version, game_ids)
game_ids.each do |id|
data = Game[id]
if (pin = data.settings['pin'])
puts "Game #{id} already pinned to #{pin}"
else
data.settings['pin'] = pin_version
end
data.save
end
end