diff options
author | Tor Andersson <tor@ccxvii.net> | 2025-04-26 00:24:05 +0200 |
---|---|---|
committer | Tor Andersson <tor@ccxvii.net> | 2025-04-26 01:26:58 +0200 |
commit | 5a6f89fe9760ff2a688d29ac5ca3bb3f28c9216f (patch) | |
tree | 26ac26aa2099c4557ae1a023e061cdfb585b4056 | |
parent | 7bcfc5845b9bfee93586f6823a0dcd3c843d0471 (diff) | |
download | server-5a6f89fe9760ff2a688d29ac5ca3bb3f28c9216f.tar.gz |
Improve rtt-patch command line parsing.
Also patch starting from a snapshot if requested.
-rwxr-xr-x | bin/rtt-patch | 116 | ||||
-rwxr-xr-x | bin/rtt-undo | 2 |
2 files changed, 89 insertions, 29 deletions
diff --git a/bin/rtt-patch b/bin/rtt-patch index 19e9874..ec0b795 100755 --- a/bin/rtt-patch +++ b/bin/rtt-patch @@ -7,12 +7,15 @@ let db = new sqlite3("db") let select_game = db.prepare("select * from games where game_id=?") let select_replay = db.prepare("select * from game_replay where game_id=?") -let delete_replay = db.prepare("delete from game_replay where game_id=?") +let delete_replay = db.prepare("delete from game_replay where game_id=? and replay_id>?") let insert_replay = db.prepare("insert into game_replay (game_id,replay_id,role,action,arguments) values (?,?,?,?,?)") -let delete_snap = db.prepare("delete from game_snap where game_id=?") +let select_last_snap = db.prepare("select max(snap_id) from game_snap where game_id=?").pluck() +let select_snap = db.prepare("select * from game_snap where game_id=? and snap_id=?") +let delete_snap = db.prepare("delete from game_snap where game_id=? and snap_id>?") let insert_snap = db.prepare("insert into game_snap(game_id,snap_id,replay_id,state) values (?,?,?,?)") +let select_state = db.prepare("select state from game_state where game_id=?").pluck() let update_state = db.prepare("update game_state set state=? where game_id=?") let update_active = db.prepare("update games set active=? where game_id=?") @@ -147,7 +150,7 @@ function finish_game(rules, state, result, message) { return state } -function patch_game(game_id, {validate_actions=true, save_snaps=true, delete_undo=false, delete_invalid=false}, verbose) { +function patch_game(game_id, {validate_actions=true, save_snaps=true, delete_undo=false, delete_invalid=false}, verbose, start_snap_id=0) { let game = select_game.get(game_id) if (!game) { console.error("game not found:", game_id) @@ -162,16 +165,46 @@ function patch_game(game_id, {validate_actions=true, save_snaps=true, delete_und if (replay.length === 0) return - console.log("processing", game_id, title_id) + let skip_replay_id = 0 + let state = null + + if (start_snap_id < 0) { + start_snap_id = select_last_snap.get(game_id) + start_snap_id + 1 + if (start_snap_id < 1) { + console.error("snap not found:", start_snap_id) + return + } + } + + if (start_snap_id > 0) { + let last_state = JSON.parse(select_state.get(game_id)) + let last_snap = select_snap.get(game_id, start_snap_id) + if (!last_snap) { + console.error("snap not found:", start_snap_id) + return + } + skip_replay_id = last_snap.replay_id + state = JSON.parse(last_snap.state) + state.undo = [] + state.log = last_state.log.slice(0, state.log) + console.log("processing", game_id, title_id, "from snapshot", start_snap_id) + } else { + console.log("processing", game_id, title_id) + } try { - let state = null let old_active = null let need_to_rewrite = false for (let i = 0; i < replay.length; ++i) { let item = replay[i] + if (item.replay_id <= skip_replay_id) { + if (verbose) + console.log("skipped:", item.replay_id, item.role, item.action, item.arguments) + continue + } + if (verbose) console.log(item.replay_id, item.role, item.action, item.arguments) @@ -192,7 +225,7 @@ function patch_game(game_id, {validate_actions=true, save_snaps=true, delete_und if (validate_actions) { if (!is_valid_action(rules, state, item.role, item.action, args)) { console.error(`invalid action: ${item.role} ${item.action} ${item.arguments}`) - console.error("\t", state.state, state.active, JSON.stringify(rules.view(state, item.role).actions)) + console.error("\t", JSON.stringify(rules.view(state, item.role).actions)) if (i < replay.length) { console.log("BROKEN ENTRIES: %d", replay.length-i) console.log(`sqlite3 db "delete from game_replay where game_id=${game_id} and replay_id>=${replay[i].replay_id}"`) @@ -227,15 +260,15 @@ function patch_game(game_id, {validate_actions=true, save_snaps=true, delete_und db.exec("begin") if (need_to_rewrite) { - delete_replay.run(game_id) + delete_replay.run(game_id, skip_replay_id) for (item of replay) if (!item.remove) insert_replay.run(game_id, item.replay_id, item.role, item.action, item.arguments) } if (save_snaps) { - delete_snap.run(game_id) - let snap_id = 0 + delete_snap.run(game_id, start_snap_id) + let snap_id = start_snap_id for (item of replay) if (item.save) insert_snap.run(game_id, ++snap_id, item.replay_id, item.state) @@ -256,36 +289,63 @@ function patch_game(game_id, {validate_actions=true, save_snaps=true, delete_und console.error("ERROR", game_id, title_id, err) if (delete_invalid) { delete_replay.run(game_id) - delete_snap.run(game_id) + delete_snap.run(game_id, 0) } } } function patch_all(options) { for (let game_id of db.prepare("select game_id from games where status=1").pluck().all()) - patch_game(game_id, options, false) + patch_game(game_id, options, false, 0) } function patch_title(title_id, options) { for (let game_id of db.prepare("select game_id from games where status=1 and title_id=?").pluck().all(title_id)) - patch_game(game_id, options, false) + patch_game(game_id, options, false, 0) } -if (process.argv.length < 3) { - process.stderr.write("usage: rtt-patch <game_id> '{options}'\n") - process.stderr.write(" or: rtt-patch <title_id> '{options}'\n") - process.stderr.write(" or: rtt-patch all '{options}'\n") - process.stderr.write('options: { "validate_actions":true, "delete_invalid":false, "save_snaps":true, "delete_undo":false }\n') - process.exit(1) -} +function main(all_args) { + var opt_args = all_args.filter(arg => arg[0] === "-" && isNaN(arg)) + var args = all_args.filter(arg => arg[0] !== "-" || !isNaN(arg)) + + if (args < 1) { + console.error("usage: rtt-patch ( GAME [ SNAP ] | TITLE | all ) [ options... ]") + console.error("\t-no-validate") + console.error("\t-no-snaps") + console.error("\t-delete-undo") + console.error("\t-delete-invalid") + process.exit(1) + } + + var options = { + validate_actions: true, + save_snaps: true, + delete_undo: false, + delete_invalid: false + } + + for (var opt of opt_args) { + if (opt === "-no-validate") options.validate_actions = false + else if (opt === "-no-snaps") options.save_snaps = false + else if (opt === "-delete-undo") options.delete_undo = true + else if (opt === "-delete-invalid") options.delete_invalid = true + else { + console.error("invalid option:", opt) + process.exit(1) + } + } -let options = {} -if (process.argv.length === 4) - options = JSON.parse(process.argv[3]) + var what = args.shift() + if (what === "all") { + patch_all(options) + } else if (isNaN(what)) { + patch_title(what, options) + } else { + var snap_id = 0 + if (args.length > 0) + snap_id = parseInt(args.shift()) + patch_game(parseInt(what), options, true, snap_id) + } +} -if (process.argv[2] === 'all') - patch_all(options) -else if (isNaN(process.argv[2])) - patch_title(process.argv[2], options) -else - patch_game(parseInt(process.argv[2]), options, true) +main(process.argv.slice(2)) diff --git a/bin/rtt-undo b/bin/rtt-undo index 2f69eed..ae375f9 100755 --- a/bin/rtt-undo +++ b/bin/rtt-undo @@ -9,7 +9,7 @@ then echo Game has $COUNT actions. fi sqlite3 db "delete from game_replay where game_id=$1 and replay_id>=$COUNT" - ./bin/rtt-patch $1 '{"validate_actions":false}' + ./bin/rtt-patch $1 -no-validate else echo "usage: rtt-undo GAME" fi |