Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions src/components/EndSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@ export function EndSummary({ game }: { game: GameState }) {
{ label: "Average speed", value: `${stats.wpm} wpm`, key: "wpm" },
{ label: "Fastest prompt", value: stats.best ? `${stats.best.wpm} wpm in ${stats.best.thread}` : "-", key: "best" },
{ label: "Accuracy", value: `${Math.round(stats.accuracy * 100)}%`, key: "accuracy" },
{ label: "Typos taken literally", value: String(stats.typosLiteral), key: "typos" },
{
label: "Parallelism",
value: `${stats.parallelism.toFixed(1)} agents on average, ${stats.peakAgents} at peak`,
key: "parallelism",
},
{ label: "Threads finished", value: `${stats.threadsDone} of ${game.threads.length}`, key: "threads" },
];
return (
Expand Down
35 changes: 4 additions & 31 deletions src/game/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ export interface Session {
correctKeystrokes: number;
promptsSent: number;
typosLiteral: number;
runningAgentMs: GameMs;
lastSampleAt: GameMs | null;
peakAgents: number;
}

export interface GameState {
Expand Down Expand Up @@ -100,9 +97,6 @@ function freshSession(): Session {
correctKeystrokes: 0,
promptsSent: 0,
typosLiteral: 0,
runningAgentMs: 0,
lastSampleAt: null,
peakAgents: 0,
};
}

Expand Down Expand Up @@ -154,10 +148,6 @@ export function isSettled(thread: ThreadState): boolean {
return thread.settledAt !== null;
}

export function runningCount(threads: ThreadState[]): number {
return threads.filter(isWorking).length;
}

export function activeThread(s: GameState = state): ThreadState {
return s.threads.find((thread) => thread.def.id === s.activeId) ?? s.threads[0]!;
}
Expand All @@ -170,8 +160,6 @@ export interface Stats {
accuracy: number;
promptsSent: number;
typosLiteral: number;
parallelism: number;
peakAgents: number;
elapsedMs: number;
threadsDone: number;
}
Expand Down Expand Up @@ -217,26 +205,13 @@ export function computeStats(s: GameState = state): Stats {
accuracy,
promptsSent: session.promptsSent,
typosLiteral: session.typosLiteral,
parallelism: elapsedMs > 0 ? session.runningAgentMs / elapsedMs : 0,
peakAgents: session.peakAgents,
elapsedMs,
threadsDone: s.threads.filter(isComplete).length,
};
}

function sampleRunningAgents(session: Session, threads: ThreadState[], now: GameMs): Session {
if (session.status !== "playing" || session.lastSampleAt === null) return session;
const running = runningCount(threads);
return {
...session,
runningAgentMs: session.runningAgentMs + running * Math.max(0, now - session.lastSampleAt),
lastSampleAt: now,
};
}

function advance(s: GameState, now: GameMs): GameState {
let changed = false;
const session = sampleRunningAgents(s.session, s.threads, now);
const threads = s.threads.map((thread) => {
const last = thread.turns.at(-1);
if (!last || last.done || now < last.startedAt + last.durationMs) return thread;
Expand All @@ -249,9 +224,9 @@ function advance(s: GameState, now: GameMs): GameState {
updatedAt: finishedAt,
};
});
let next: GameState = { ...s, threads: changed ? threads : s.threads, session, now };
let next: GameState = { ...s, threads: changed ? threads : s.threads, now };
next = autoSettle(next, now);
if (session.status === "playing" && next.threads.every(isComplete)) {
if (s.session.status === "playing" && next.threads.every(isComplete)) {
next = endSession(next, "done", now);
}
return next;
Expand Down Expand Up @@ -282,7 +257,7 @@ function autoSettle(s: GameState, now: GameMs): GameState {
function endSession(s: GameState, reason: "done", at: GameMs): GameState {
return {
...s,
session: { ...s.session, status: "ended", endReason: reason, endedAt: at, lastSampleAt: null },
session: { ...s.session, status: "ended", endReason: reason, endedAt: at },
};
}

Expand Down Expand Up @@ -311,7 +286,7 @@ function canType(thread: ThreadState): boolean {

function startIfReady(s: GameState, now: GameMs): GameState {
if (s.session.status !== "ready") return s;
return { ...s, session: { ...s.session, status: "playing", startedAt: now, lastSampleAt: now } };
return { ...s, session: { ...s.session, status: "playing", startedAt: now } };
}

export function typeChar(ch: string) {
Expand Down Expand Up @@ -391,8 +366,6 @@ export function send() {
draftCorrectKeys: 0,
updatedAt: now,
}));
const running = runningCount(s.threads);
s = { ...s, session: { ...s.session, peakAgents: Math.max(s.session.peakAgents, running) } };
set(s);
}

Expand Down
3 changes: 1 addition & 2 deletions tests/play.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,13 @@ async function playFullSessionInDark(browser) {
check(end.stats.promptsSent === totalPrompts, `sent all ${totalPrompts} prompts (got ${end.stats.promptsSent})`);
check(end.stats.typosLiteral >= typoPrompts, `typos taken literally: ${end.stats.typosLiteral} for ${typoPrompts} typo prompts`);
check(switchesWhileRunning >= 5, `switched threads while an agent ran ${switchesWhileRunning} times`);
check(end.stats.parallelism > 1, `parallelism above 1 (got ${end.stats.parallelism.toFixed(2)})`);
check(end.stats.accuracy < 1 && end.stats.accuracy > 0.9, `accuracy is plausible (${(end.stats.accuracy * 100).toFixed(1)}%)`);
check(end.stats.wpm > 0, `wpm is positive (${end.stats.wpm})`);
const literal = end.threads.flatMap((t) => t.turns).filter((turn) => turn.reply.literal);
const quotesTypo = literal.every((turn) => turn.diff.typos.length === 0 || turn.reply.text.includes(turn.diff.typos[0].typed));
check(literal.length > 0 && quotesTypo, `${literal.length} literal replies quote the typo as typed`);
const summary = await page.locator("[data-summary]").allTextContents();
check(summary.length === 7, `end screen shows ${summary.length} stat rows`);
check(summary.length === 5, `end screen shows ${summary.length} stat rows`);
check(errors.length === 0, `no console errors in dark run${errors.length ? `: ${errors.join(" | ")}` : ""}`);

await page.keyboard.press("Enter");
Expand Down
Loading