@@ -5,16 +5,16 @@ LOG = {
55 mod_path = nil ,
66 current_run_file = nil ,
77 pending_logs = {},
8- previous_game_state = nil ,
8+ game_state_before = {} ,
99}
1010
1111-- =============================================================================
1212-- Utility Functions
1313-- =============================================================================
1414
1515--- Writes a log entry to the JSONL file
16- --- @param log_entry table The log entry to write
17- local function write_log_entry (log_entry )
16+ --- @param log_entry LogEntry The log entry to write
17+ function LOG . write (log_entry )
1818 if LOG .current_run_file then
1919 local log_line = json .encode (log_entry ) .. " \n "
2020 local file = io.open (LOG .current_run_file , " a" )
3131function LOG .update ()
3232 for key , pending_log in pairs (LOG .pending_logs ) do
3333 if pending_log .condition () then
34+ -- Update the log entry with after function call info
35+ pending_log .log_entry [" timestamp_ms_after" ] = math.floor (socket .gettime () * 1000 )
3436 pending_log .log_entry [" game_state_after" ] = utils .get_game_state ()
35- write_log_entry (pending_log .log_entry )
36- LOG .previous_game_state = pending_log .log_entry .game_state_after
37+ LOG .write (pending_log .log_entry )
38+ -- Prepare for the next log entry
39+ LOG .game_state_before = pending_log .log_entry .game_state_after
3740 LOG .pending_logs [key ] = nil
3841 end
3942 end
4043end
4144
42- --- Logs a function call to the JSONL file with completion waiting
43- --- @param original_function function The original function being called
45+ --- Schedules a log entry to be written when the condition is met
4446--- @param function_call FunctionCall The function call to log
45- function LOG .write (original_function , function_call , ...)
47+ function LOG .schedule_write (function_call )
48+ sendInfoMessage (function_call .name .. " (" .. json .encode (function_call .arguments ) .. " )" , " LOG" )
49+
4650 local log_entry = {
47- timestamp_ms = math.floor (socket .gettime () * 1000 ),
4851 [" function" ] = function_call ,
49- game_state_before = LOG .previous_game_state ,
52+ -- before function call
53+ timestamp_ms_before = math.floor (socket .gettime () * 1000 ),
54+ game_state_before = LOG .game_state_before ,
55+ -- after function call (will be filled in by LOG.write)
56+ timestamp_ms_after = nil ,
57+ game_state_after = nil ,
58+ }
59+ local pending_key = function_call .name .. " _" .. tostring (socket .gettime ())
60+ LOG .pending_logs [pending_key ] = {
61+ log_entry = log_entry ,
62+ condition = utils .COMPLETION_CONDITIONS [function_call .name ],
5063 }
51-
52- local result = original_function (... )
53- sendInfoMessage (function_call .name .. " (" .. json .encode (function_call .arguments ) .. " )" , " LOG" )
54-
55- -- Get completion condition by function name
56- local condition = utils .COMPLETION_CONDITIONS [function_call .name ]
57- if condition then
58- -- Create a unique key for the pending log
59- local pending_key = function_call .name .. " _" .. tostring (socket .gettime ())
60- LOG .pending_logs [pending_key ] = {
61- log_entry = log_entry ,
62- condition = condition ,
63- }
64- else
65- -- Immediate logging if no condition found
66- log_entry [" game_state_after" ] = utils .get_game_state ()
67- write_log_entry (log_entry )
68- LOG .previous_game_state = log_entry .game_state_after
69- end
70-
71- return result
7264end
7365
7466-- =============================================================================
@@ -87,7 +79,8 @@ function hook_go_to_menu()
8779 name = " go_to_menu" ,
8880 arguments = {},
8981 }
90- return LOG .write (original_function , function_call , ... )
82+ LOG .schedule_write (function_call )
83+ return original_function (... )
9184 end
9285 sendDebugMessage (" Hooked into G.FUNCS.go_to_menu for logging" , " LOG" )
9386end
@@ -124,7 +117,8 @@ function hook_start_run()
124117 challenge = args .challenge and args .challenge .name ,
125118 },
126119 }
127- return LOG .write (original_function , function_call , game_state , args )
120+ LOG .schedule_write (function_call )
121+ return original_function (game_state , args )
128122 end
129123 sendDebugMessage (" Hooked into G.FUNCS.start_run for logging" , " LOG" )
130124end
@@ -138,7 +132,8 @@ function hook_select_blind()
138132 local original_function = G .FUNCS .select_blind
139133 G .FUNCS .select_blind = function (args )
140134 local function_call = { name = " skip_or_select_blind" , arguments = { action = " select" } }
141- return LOG .write (original_function , function_call , args )
135+ LOG .schedule_write (function_call )
136+ return original_function (args )
142137 end
143138 sendDebugMessage (" Hooked into G.FUNCS.select_blind for logging" , " LOG" )
144139end
@@ -148,7 +143,8 @@ function hook_skip_blind()
148143 local original_function = G .FUNCS .skip_blind
149144 G .FUNCS .skip_blind = function (args )
150145 local function_call = { name = " skip_or_select_blind" , arguments = { action = " skip" } }
151- return LOG .write (original_function , function_call , args )
146+ LOG .schedule_write (function_call )
147+ return original_function (args )
152148 end
153149 sendDebugMessage (" Hooked into G.FUNCS.skip_blind for logging" , " LOG" )
154150end
@@ -168,7 +164,8 @@ function hook_play_cards_from_highlighted()
168164 end
169165 end
170166 local function_call = { name = " play_hand_or_discard" , arguments = { action = " play_hand" , cards = cards } }
171- return LOG .write (original_function , function_call , ... )
167+ LOG .schedule_write (function_call )
168+ return original_function (... )
172169 end
173170 sendDebugMessage (" Hooked into G.FUNCS.play_cards_from_highlighted for logging" , " LOG" )
174171end
@@ -184,7 +181,8 @@ function hook_discard_cards_from_highlighted()
184181 end
185182 end
186183 local function_call = { name = " play_hand_or_discard" , arguments = { action = " discard" , cards = cards } }
187- return LOG .write (original_function , function_call , ... )
184+ LOG .schedule_write (function_call )
185+ return original_function (... )
188186 end
189187 sendDebugMessage (" Hooked into G.FUNCS.discard_cards_from_highlighted for logging" , " LOG" )
190188end
@@ -198,7 +196,8 @@ function hook_cash_out()
198196 local original_function = G .FUNCS .cash_out
199197 G .FUNCS .cash_out = function (...)
200198 local function_call = { name = " cash_out" , arguments = {} }
201- return LOG .write (original_function , function_call , ... )
199+ LOG .schedule_write (function_call )
200+ return original_function (... )
202201 end
203202 sendDebugMessage (" Hooked into G.FUNCS.cash_out for logging" , " LOG" )
204203end
@@ -212,7 +211,8 @@ function hook_toggle_shop()
212211 local original_function = G .FUNCS .toggle_shop
213212 G .FUNCS .toggle_shop = function (...)
214213 local function_call = { name = " shop" , arguments = { action = " next_round" } }
215- return LOG .write (original_function , function_call , ... )
214+ LOG .schedule_write (function_call )
215+ return original_function (... )
216216 end
217217 sendDebugMessage (" Hooked into G.FUNCS.toggle_shop for logging" , " LOG" )
218218end
@@ -273,34 +273,30 @@ function hook_hand_rearrange()
273273 arguments = { cards = cards },
274274 }
275275
276- --- NOTE: we cannot use LOG.write because we do not have access to game_state_before. We need to recreate it.
277- --- The following lines corresponds to LOG.write
276+ -- NOTE: we cannot schedule a log write because we don't have access to the
277+ -- state before the function call. We need to recreate it.
278+
279+ -- HACK: we cannot compute the timestamp before in the right way the function
280+ -- call because because this hook run with the game loop. So we use the
281+ -- timestamp for after and before
282+
283+ local timestamp_ms = math.floor (socket .gettime () * 1000 )
278284
279285 local log_entry = {
280- timestamp_ms = math.floor (socket .gettime () * 1000 ),
281286 [" function" ] = function_call ,
282- game_state_before = previous_game_state ,
287+ timestamp_ms_before = timestamp_ms ,
288+ game_state_before = LOG .game_state_before ,
289+ timestamp_ms_after = timestamp_ms ,
283290 game_state_after = utils .get_game_state (),
284291 }
285- LOG .previous_game_state = log_entry .game_state_after
286292
287293 sendInfoMessage (function_call .name .. " (" .. json .encode (function_call .arguments ) .. " )" , " LOG" )
288-
289- if LOG .current_run_file then
290- local log_line = json .encode (log_entry ) .. " \n "
291- local file = io.open (LOG .current_run_file , " a" )
292- if file then
293- file :write (log_line )
294- file :close ()
295- else
296- sendErrorMessage (" Failed to open log file for writing: " .. LOG .current_run_file , " LOG" )
297- end
298- end
294+ LOG .write (log_entry )
295+ LOG .game_state_before = log_entry .game_state_after
299296 end
300297 end
301298
302299 previous_order = current_order
303- previous_game_state = utils .get_game_state ()
304300 return result
305301 else
306302 -- For non-hand card areas, just call the original function
0 commit comments