owenrusk.dev

casebench

test cases straight onto the board.

git clone https://owenrusk.dev/casebench.git

commit 2800d87e6a72a7f65bb8bf00342dd62d719e4bb9
parent 662cc35b720ed1bb4e6b9b3ee23d05e856419ba9
author Owen Rusk <owen@papermothgames.com>
date   2025-05-14 13:45:12 -0500
unlock
casebench/cli.py+12-0
casebench/db.py+8-0
diff --git a/casebench/cli.py b/casebench/cli.py
index 31eaa7a..b9bc20c 100644
--- a/casebench/cli.py
+++ b/casebench/cli.py
@@ -37,6 +37,11 @@ def main(argv: list[str] | None = None) -> int:
     locker.add_argument("--text", default="locked.", help="what the lock says (default: locked.)")
     locker.set_defaults(run=run_lock)
 
+    unlocker = sub.add_parser("unlock", help="take the lock off a case")
+    unlocker.add_argument("case")
+    unlocker.add_argument("--player", required=True)
+    unlocker.set_defaults(run=run_unlock)
+
     args = parser.parse_args(argv)
     dsn = os.environ.get("CASEBENCH_DSN")
     if not dsn:
@@ -88,3 +93,10 @@ def run_lock(conn: psycopg.Connection, args: argparse.Namespace) -> None:
         raise Fail(str(e)) from None
     db.lock(conn, who, args.case, new)
     print(f"{args.player}: locked {args.case}")
+
+
+def run_unlock(conn: psycopg.Connection, args: argparse.Namespace) -> None:
+    who = player(conn, args.player)
+    if not db.unlock(conn, who, args.case):
+        raise Fail(f"{args.case} isn't locked for {args.player}")
+    print(f"{args.player}: unlocked {args.case}")
diff --git a/casebench/db.py b/casebench/db.py
index 943ab8e..6ba3fef 100644
--- a/casebench/db.py
+++ b/casebench/db.py
@@ -76,3 +76,11 @@ def lock(conn: psycopg.Connection, player: str, case_id: str, new: Lock) -> None
         (player, case_id, new.text, new.lines, new.salt, new.hash),
     )
     conn.commit()
+
+
+def unlock(conn: psycopg.Connection, player: str, case_id: str) -> bool:
+    gone = conn.execute(
+        "delete from board_locks where player_id = %s and case_id = %s", (player, case_id)
+    ).rowcount
+    conn.commit()
+    return gone > 0