Triviaverse / src /lib /spark /engine.ts
Simeon Garratt
feat(spark): rewrite state machine for conversational flow
f50ed9e
Raw
History Blame Contribute Delete
3.14 kB
import type { DebateState, DebateAction } from "./types";
export function createInitialDebateState(): DebateState {
return {
phase: "idle",
debateId: null,
config: null,
topicOptions: [],
selectedTopic: null,
myVote: null,
opponentVoted: false,
currentRound: 0,
rounds: [],
currentOpener: "player1",
currentOpeningArg: "",
myArgument: "",
momentum: 0,
verdict: null,
eloChange: 0,
challengeResult: null,
};
}
export function debateReducer(state: DebateState, action: DebateAction): DebateState {
switch (action.type) {
case "SET_CONFIG":
return { ...state, phase: "config", config: action.config };
case "SET_TOPICS":
return { ...state, phase: "topic-select", topicOptions: action.topics };
case "ADD_TOPIC":
return { ...state, topicOptions: [...state.topicOptions, action.topic] };
case "VOTE_TOPIC":
return { ...state, myVote: action.topicId };
case "OPPONENT_VOTED":
return { ...state, opponentVoted: true };
case "SELECT_TOPIC":
return {
...state,
phase: "round-open",
selectedTopic: action.topic,
currentRound: 1,
currentOpener: "player1",
currentOpeningArg: "",
myArgument: "",
};
case "START_ROUND":
return {
...state,
phase: "round-open",
currentRound: state.currentRound + 1,
currentOpener: state.currentOpener === "player1" ? "player2" : "player1",
currentOpeningArg: "",
myArgument: "",
};
case "SET_OPENING_ARG":
return {
...state,
phase: "round-rebuttal",
currentOpeningArg: action.argument,
myArgument: "",
};
case "START_REBUTTAL":
return { ...state, phase: "round-rebuttal" };
case "UPDATE_ARGUMENT":
return { ...state, myArgument: action.text };
case "COMPLETE_ROUND":
return {
...state,
phase: "commentary",
rounds: [...state.rounds, action.round],
};
case "SET_COMMENTARY": {
const lastRound = state.rounds[state.rounds.length - 1];
if (!lastRound) return state;
const updatedRound = { ...lastRound, commentary: action.commentary };
return {
...state,
rounds: [...state.rounds.slice(0, -1), updatedRound],
momentum: state.momentum + action.commentary.momentum,
};
}
case "START_JUDGING":
return { ...state, phase: "judging" };
case "SET_VERDICT":
return {
...state,
phase: "verdict",
verdict: action.verdict,
eloChange: action.eloChange,
};
case "START_CHALLENGE":
return { ...state, phase: "challenge" };
case "SET_CHALLENGE_RESULT":
return {
...state,
phase: "verdict",
challengeResult: action.result,
verdict: action.result.newVerdict ?? state.verdict,
eloChange: action.newEloChange,
};
case "FINISH":
return { ...state, phase: "done" };
case "RESET":
return createInitialDebateState();
default:
return state;
}
}