A seat's view carries its own move in waiting and its move in the last round it played
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
927e49cf79
commit
8e35d3a3a6
+4
-1
@@ -132,7 +132,10 @@ if it were never there.
|
||||
- `seatsFor(options)`: fewer seats for some table options.
|
||||
- `settled(input)`: whether an input is final. A game with drafts answers
|
||||
false until the player says it is done; a draft may be replaced, and the
|
||||
round waits for every seat's settled input.
|
||||
round waits for every seat's settled input. A seat's view carries its
|
||||
own input in waiting (`yourInput`), so a page reopened shows the draft,
|
||||
and its input in the last round it played (`yourLastInput`), so the page
|
||||
can tell it what became of its own choice.
|
||||
- `tally(state)`: the game's own lines for the tally, from a finished game.
|
||||
- `preferences`, `options`: the preferences panel's settings and the
|
||||
host's table choices (above).
|
||||
|
||||
@@ -63,4 +63,17 @@ describe('rooms', () => {
|
||||
rooms.submit(room, bo, { pick: 1, final: true }, 1);
|
||||
expect(() => rooms.submit(room, bo, { pick: 2 }, 1)).toThrow(/not your move/);
|
||||
});
|
||||
|
||||
it("shows a seat its own move in waiting and its last move played, and nobody else's", () => {
|
||||
const { rooms, room, ann, bo } = table();
|
||||
rooms.submit(room, ann, { pick: 5 }, 0);
|
||||
expect(rooms.view(room, 'A').yourInput).toEqual({ pick: 5 });
|
||||
expect(rooms.view(room, 'B').yourInput).toBeNull();
|
||||
expect(rooms.view(room, '').yourInput).toBeNull();
|
||||
rooms.submit(room, bo, { pick: 2 }, 0);
|
||||
expect(rooms.view(room, 'A').yourInput).toBeNull();
|
||||
expect(rooms.view(room, 'A').yourLastInput).toEqual({ pick: 5 });
|
||||
expect(rooms.view(room, 'B').yourLastInput).toEqual({ pick: 2 });
|
||||
expect(rooms.view(room, '').yourLastInput).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -48,6 +48,8 @@ export interface Room<State> {
|
||||
state: State | null;
|
||||
/** Inputs received for the round in progress, by seat. */
|
||||
pending: Record<SeatId, unknown>;
|
||||
/** Each seat's input in the last round it played, kept through rounds it had no part in; each seat is shown only its own. */
|
||||
played: Record<SeatId, unknown>;
|
||||
chat: ChatLine[];
|
||||
/** Rounds played so far; a move names the count it was made against. */
|
||||
resolved: number;
|
||||
@@ -192,7 +194,7 @@ export class Rooms<State, Input> {
|
||||
|
||||
/** A table with nobody seated yet. */
|
||||
private blank(id: string, size: number, createdAt: number, rematchOf: string | null, expected: string[], options: TableOptions, seq = 0): Room<State> {
|
||||
return { id, size, createdAt, seats: [], galleryTalk: false, challenge: null, expected, rematch: null, rematchOf, options, over: false, state: null, pending: {}, chat: [], resolved: 0, seq, updatedAt: createdAt };
|
||||
return { id, size, createdAt, seats: [], galleryTalk: false, challenge: null, expected, rematch: null, rematchOf, options, over: false, state: null, pending: {}, played: {}, chat: [], resolved: 0, seq, updatedAt: createdAt };
|
||||
}
|
||||
|
||||
/** Open a table with its first seat taken; a rematch names the table it follows and holds seats for its players. */
|
||||
@@ -418,6 +420,7 @@ export class Rooms<State, Input> {
|
||||
|
||||
/** The view for a seat, or for the gallery when the seat is SPECTATOR. */
|
||||
view(room: Room<State>, seatId: SeatId): RoomView<State> {
|
||||
const seated = seatId !== SPECTATOR;
|
||||
return {
|
||||
roomId: room.id,
|
||||
seq: room.seq,
|
||||
@@ -430,6 +433,8 @@ export class Rooms<State, Input> {
|
||||
resolved: room.resolved,
|
||||
over: room.state ? this.game.over(room.state) : null,
|
||||
state: room.state ? this.game.view(room.state, seatId) : null,
|
||||
yourInput: seated && seatId in room.pending ? room.pending[seatId] : null,
|
||||
yourLastInput: seated && seatId in room.played ? room.played[seatId] : null,
|
||||
chat: room.chat,
|
||||
audience: this.gallery.get(room.id) ?? 0,
|
||||
galleryTalk: room.galleryTalk,
|
||||
@@ -512,6 +517,7 @@ export class Rooms<State, Input> {
|
||||
case 'turn':
|
||||
if (!room.state) return;
|
||||
room.state = this.game.resolve(room.state, line.inputs as Record<SeatId, Input>);
|
||||
room.played = { ...room.played, ...(line.inputs as Record<SeatId, unknown>) };
|
||||
room.pending = {};
|
||||
room.resolved += 1;
|
||||
break;
|
||||
|
||||
@@ -29,6 +29,10 @@ export interface RoomView<State> {
|
||||
turn: number | null;
|
||||
over: Outcome | null;
|
||||
state: State | null;
|
||||
/** This seat's input for the round in progress, as the server holds it (a draft, or a settled move); null for none, and for the gallery. */
|
||||
yourInput: unknown;
|
||||
/** This seat's input in the last round it played, for telling it what became of its own choice; null for none, and for the gallery. */
|
||||
yourLastInput: unknown;
|
||||
chat: ChatLine[];
|
||||
/** How many watch from the Peanut Gallery. */
|
||||
audience: number;
|
||||
|
||||
Reference in New Issue
Block a user