User Stats & Preferences
Relevant source files
The following files were used as context for generating this wiki page:
User Stats & Preferences comprise the systems responsible for persisting user-specific configuration, game session state, and historical performance metrics. These systems facilitate features such as theme and language selection, cross-device session rejoining, and the tracking of competitive statistics like win rates and high scores.
The architecture utilizes a dual-layer storage approach: local persistence via localStorage for immediate client-side responsiveness (particularly for anonymous users) and cloud persistence via Convex for authenticated users. This ensures that user settings and progress are maintained whether the user is playing as a guest or via a registered account.
Data Models & Schema
The system relies on three primary tables defined in the Convex schema to track user-related data: userPreferences, userStats, and matchPlayers.
Entity Relationship Diagram
The following diagram illustrates how user preferences and statistics relate to the core authentication and match tracking tables.
Sources: convex/schema.ts:88-142
Table Definitions
| Table | Purpose | Key Fields |
|---|---|---|
userPreferences | Stores UI settings and session state. | userId, theme, language, activeRoomId, localGameState. |
userStats | Aggregated performance metrics for a user. | gamesPlayed, gamesWon, totalScore, bestScore. |
matchPlayers | Junction table for user performance in specific matches. | matchId, userId, finalScore, place. |
Sources: convex/schema.ts:114-142
User Preferences Management
User preferences manage the visual and functional behavior of the application. This includes UI customization (theme, language) and session management (rejoining games).
Backend Implementation (Convex)
The backend provides mutations to update specific preference fields. These functions require an authenticated user; if a user is not authenticated, specific handlers like setActiveSession may return early or throw errors.
- Update Preferences: The
updatemutation allows batch updating ofdisplayName,theme,language, andsoundEnabled. - Session Persistence:
setActiveSessionandclearActiveSessionmanage theactiveRoomIdandactivePlayerIdto allow users to rejoin games after a refresh. - Local State Backup:
saveLocalGameStatestores a snapshot of the game state for "hotseat" mode resumption.
Sources: convex/userPreferences.ts:44-160, convex/userPreferences.ts:221-255
Client-Side Management
The useUserPreferences hook provides a unified interface for managing these settings, defaulting to safeLocalStorage for immediate access.
Key Preference Actions
| Function | Source | Description |
|---|---|---|
setTheme | Hook/Mutation | Updates theme ("light"/"dark") and dispatches dreamcats-theme-changed. |
setLanguage | Hook/Mutation | Updates i18n language code (e.g., "en", "pl"). |
setTutorialCompleted | Hook/Mutation | Persists a boolean to skip introductory guides. |
saveActiveSession | Hook | Stores roomId and playerId in JSON format to dreamcats-active-session. |
Sources: src/hooks/useUserPreferences.ts:34-75, convex/userPreferences.ts:79-158
User Statistics & Match History
The statistics system aggregates data from completed matches to provide an overview of player performance.
Statistics Retrieval Logic
The getMyOverview query retrieves both the aggregate statistics from userStats and a list of recent match participations from matchPlayers. It performs a join-like operation by fetching the associated matches document for each participation record to resolve the winner's name and match mode.
Sources: convex/stats.ts:6-55
Statistics Calculation
In the ProfileStatsDialog component, raw data from the backend is processed into derived metrics:
- Win Rate:
Math.round((gamesWon / gamesPlayed) * 100) - Average Score:
Math.round(totalScore / gamesPlayed) - Best Score: The lowest score achieved (since the goal is to have the fewest points).
Sources: src/components/ProfileStatsDialog.tsx:31-40
Sequence: Viewing Profile Stats
Global State Integration
Preferences are integrated into the global useAppStore (Zustand) for application-wide access. This allows components to react to changes in player names, themes, or locale.
- Session Slice: Stores
playerId,playerName,locale,theme, andauthToken. - UI Slice: Manages
reducedMotionpreferences andisMenuOpenstates. - Syncing: The store includes
setThemeandsetLocaleactions that update the global state, which are typically invoked alongside the persistence hooks.
Sources: src/tests/store.test.ts:25-75
Summary
The User Stats & Preferences module provides the foundation for personalizing the Dreamcats experience. By combining Convex's real-time capabilities with local storage fallbacks, the system ensures that user identities, UI preferences, and competitive histories remain consistent across sessions and devices. This architecture supports both casual guest play and authenticated progression tracking.