From 6883b707adf50925f028cce7b4036925a691484a Mon Sep 17 00:00:00 2001 From: rope Date: Tue, 20 Oct 2026 20:11:11 +0100 Subject: [PATCH] Remove finished work orders Co-Authored-By: Claude Opus 5.5 --- app.py | 2 ++ game.py | 10 ++++++++++ static/app.js | 9 +++++++-- tests/test_game.py | 9 +++++++++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/app.py b/app.py index aa5f003..d038f9a 100644 --- a/app.py +++ b/app.py @@ -330,6 +330,8 @@ class Handler(BaseHTTPRequestHandler): return game.provide_reagent(world, player, body.get("id"), str(item)) if path == "/api/order/cancel": return game.cancel_order(world, player, body.get("id"), now) + if path == "/api/order/remove": + return game.remove_orders(world, player, body.get("id")) if path == "/api/order/work": return game.work_order(world, player, body.get("id"), now) if path == "/api/order/drop": diff --git a/game.py b/game.py index 11e8c4e..d6446a1 100644 --- a/game.py +++ b/game.py @@ -2285,6 +2285,16 @@ def cancel_order(world: dict, player: dict, order_id, now: float) -> str | None: return None +def remove_orders(world: dict, player: dict, order_id=None) -> str | None: + """Clear your finished orders: one, or all of them. Ones still holding items for your bank stay.""" + gone = [o for o in world["orders"] if o["by"] == player["id"] and o["status"] != "open" and not o["held"] + and order_id in (None, o["id"])] + if not gone: + return "No such order" + world["orders"] = [o for o in world["orders"] if o not in gone] + return None + + def claim_order(world: dict, player: dict, order_id, claim: bool = True) -> str | None: order = order_by_id(world, order_id) if not order or order["status"] != "open" or order["kind"] != "craft": diff --git a/static/app.js b/static/app.js index e034b9a..2045331 100644 --- a/static/app.js +++ b/static/app.js @@ -1240,6 +1240,7 @@ function orderCard(o) { let buttons = "", status = ""; if (o.status !== "open") { status = `${{ done: "Done", cancelled: "Cancelled", expired: "Expired" }[o.status]}`; + if (mine && !o.held) buttons = ``; } else if (mine) { buttons = ``; if (o.claimed) status = `${esc(playerName(o.claimed))}`; @@ -1336,12 +1337,14 @@ function orders() { const lists = { take: takeable, open, yours }; if (!lists[orderTab]) orderTab = "take"; const shown = lists[orderTab]; - const tab = (key, label, n) => ``; + const old = orderTab === "yours" && yours.some((o) => o.status !== "open" && !o.held); + const tab =(key, label, n) => ``; return `
${ORDER_ICON()}

Work orders

${draft ? orderComposer() : ""} -
${tab("take", "For you", takeable.length)}${tab("open", "All open", 0)}${tab("yours", "Yours", 0)}
+
${tab("take", "For you", takeable.length)}${tab("open", "All open", 0)}${tab("yours", "Yours", 0)} + ${old ? `` : ""}
${shown.length ? `
${shown.map(orderCard).join("")}
` : `

None.

`}`; } @@ -1664,6 +1667,8 @@ document.addEventListener("click", (e) => { if (d.orderDrop) return act("/api/order/drop", { id: Number(d.orderDrop) }); if (d.orderDeliver) return act("/api/order/deliver", { id: Number(d.orderDeliver) }); if (d.orderCancel) return act("/api/order/cancel", { id: Number(d.orderCancel) }); + if (d.orderRemove) return act("/api/order/remove", { id: Number(d.orderRemove) }); + if ("orderClear" in d) return act("/api/order/remove", {}); if (d.orderFill) return act("/api/order/provide", { id: Number(d.orderFill), item: d.item }); if (d.doll) { dollPick = dollPick === d.doll ? null : d.doll; diff --git a/tests/test_game.py b/tests/test_game.py index a661f97..44ec793 100644 --- a/tests/test_game.py +++ b/tests/test_game.py @@ -1609,6 +1609,15 @@ class WorkOrderTest(unittest.TestCase): self.assertEqual(self.mike["gold"], 200) self.assertEqual(self.mike["bank"]["iron_bar"], 3) + def test_finished_orders_can_be_removed(self): + self.post_hammer() + order = self.world["orders"][0] + self.assertEqual(game.remove_orders(self.world, self.mike, order["id"]), "No such order") # still open + game.cancel_order(self.world, self.mike, order["id"], T0) + self.assertEqual(game.remove_orders(self.world, self.fred, order["id"]), "No such order") # not his + self.assertIsNone(game.remove_orders(self.world, self.mike)) + self.assertEqual(self.world["orders"], []) + def test_requester_can_fill_a_slot_after_posting(self): self.mike["gold"] = 200 self.mike["bank"] = {"iron_bar": 3, "clay_core": 3}