Public: anyone can read this; the crew can change it.

The table plays on the page: the charter, the standing offer, the log and the three acts — before the reveal exists #75

open not picked up yet opened this
opened this

Intent. Let a person play a turn from a phone with what is already built, instead of waiting for the binding.

The split. #12 is "the whole game server-rendered, live, playable with a thumb" and waits on #10, the binding and the reveal — which is right for the reveal and wrong for everything else. Measured on main today (948abc0): a table can be started, offered on, accepted and passed entirely over HTTP, and /tables/1 shows the title, the seats and "The seats are fixed: this table has started." No charter, no charge, no offer, no log, no buttons, and its data-live does not even list act.made, so an act does not refresh it. The parts to draw all of it already exist in src/pages/table.ts and are shown at /style. This issue is the pre-reveal half; #12 keeps the reveal, the settlement and the polish that needs them.

Done looks like

  • [ ] /tables/:id renders, for a playing table: the charter grid with the standing offer marked, the viewer's own charge (theirs alone), whose turn it is with the seat named, the act log newest-last with each acceptance's sworn aim, and what the standing offer would pay the viewer (your_payoff).
  • [ ] The three acts, as forms that post to the routes that exist: offer (a setting per clause, the charter grid as the control), accept (with the choice of which aim to swear when §6 offers more than one), pass. Each is drawn exactly when may says so and never otherwise, and a refusal comes back as the notice, in the action's own words.
  • [ ] A start button for the host, from canStart.
  • [ ] Live: the region lists act.made and turn.changed as well as the seat events, so an act made at another door appears without a reload.
  • [ ] 360px with no horizontal scroll, every control 44px on a side, and the whole page server-rendered — the first paint is playable with JavaScript off.
  • [ ] No new markup for a part that src/pages/table.ts already has; anything new goes there and is shown at /style from a fixture.
  • [ ] Tests: the seat to act sees the three controls, another seat sees none, a guest sees no charge and no controls, and posting an offer from the page moves the turn.

Files I expect to change. src/pages/tableview.ts, src/pages/table.ts, src/routes.ts (the form posts for offer, accept, pass and start), src/pages/style.ts, static/app.css, src/server.test.ts, src/pages/style.test.ts.

Risks. An offer is irreversible and an acceptance spends a truth forever: the page says so before it posts. Do not let the page compute a rule — everything it draws comes from the state. Keep the log bounded once it is long (that is its own issue).

Who. @mason, reviewed by @juniper. Waits on the may/your_payoff state issue below it.

commented

One measurement for the log, so the page does not inherit an unbounded read: with 300 acts in the ledger (a fortnight of 15-minute windows would be thousands), GET /api/tables/1 on main is 30 KB and 14 ms, against 2 KB and 6 ms for the same table empty. Every live refresh refetches the whole page, so an unbounded log is refetched with it. Show the latest acts with a count and a way back through the older ones, and keep what src/round.ts reads for its arithmetic separate from what the view hands out — the turn is derived from the act count, so bounding the wrong one changes the game.

commented

The bound on the act log now has its own issue — #79, with the measurement (30 KB and 14 ms at 300 acts, against 2 KB and 6 ms empty) and the rule that matters: bound what the view hands out, never what the arithmetic reads. This page issue can show the latest acts and defer the paging to it; if #79 lands first, take the slice it gives you.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs