The Simulation State is the central state management layer that powers the interactive veterinary communication simulations. It is responsible for coordinating learning content (skills and cases) with live AI-driven conversations, ensuring a consistent and predictable simulation experience.
The state is implemented using Zustand, providing a lightweight, reactive store for both UI and simulation logic.
The simulation state serves four primary purposes:
Manage the live conversation between the user and the AI
Track the currently active skill
Store and normalize all skills and cases
Track which case is selected for each skill
It acts as the single source of truth for an active simulation session.
interface SimulationState {
conversation: Message[];
setConversation: (
updater: Message[] | ((prev: Message[]) => Message[])
) => void;
clearConversation: () => void;
currentSkill: number;
setCurrentSkill: (skillId: number) => void;
skills: Skill[];
setSelectedCase: (skillId: number, caseId: string) => void;
}
conversation: Message[]
Stores the entire dialogue history for the current simulation.
Why it matters
Enables chat-based simulation
Supports reflection, replay, and future assessment
Allows incremental AI message updates
currentSkill: number
Tracks which skill the learner is currently practicing.
Example
currentSkill = 2
Meaning:
The learner is practicing Skill #2
skills: Skill[]
Contains all skills across all levels, including their cases and metadata.
This data is pre-processed before entering state:
Levels and ordering are assigned
Missing case gender is inferred
Each skill tracks its selected case
setConversation(updater)
Updates the conversation state.
Supports:
Direct replacement
Functional updates
Recommended usage
setConversation(prev => [...prev, newMessage])
This prevents race conditions during streaming AI responses.
clearConversationclearConversation()
Resets the conversation to an empty state.
Used when
Starting a new case
Restarting a simulation
Switching skills
setCurrentSkillsetCurrentSkill(skillId)
Sets the active skill.
Typically paired with:
UI updates
Case selection
Conversation reset (handled externally)
setSelectedCasesetSelectedCase(skillId, caseId)
Marks a case as selected for a specific skill.
Behavior
Updates only the targeted skill
Preserves state for all other skills
This allows:
Switching skills without losing progress
Remembering previous case selections
Represents one turn in the simulation conversation.
interface Message {
id: string; role: "user" | "assistant";
content: string;
audio?: string;
loading?: boolean;
}
Usage
Stores both user input and AI responses
Supports streaming (loading)
Allows future audio playback support
See Skill
See Case