Umfangreiche Erweiterung der Skill-Bibliothek: Neue Skills für Humanisierung (Englisch/PT-BR), Design-Validierung, AI-SEO und Coolify-Deployment inkl. Regelwerke, Presets, Pattern-Referenzen, Testfälle und Automatisierungsskripte. Zusätzliche Skills für Revenue-Centric Design, Pier Cloud, OKF, Lebenslauf- und LinkedIn-Optimierung sowie zahlreiche Referenzdateien, Checklisten und YAML/JSON/Markdown-Templates. Einführung einer vollständigen OpenWiki-Dokumentation mit Architektur-, Domain- und Workflow-Beschreibungen, zentralem Index und automatisierten Updates. Modularer Aufbau, restriktive Lizenzen und umfassende Qualitäts- und Evaluationsmechanismen für alle neuen Inhalte.
172 lines
6.7 KiB
Markdown
172 lines
6.7 KiB
Markdown
---
|
|
type: Domain Model
|
|
title: Game Domain & State Models
|
|
description: Detailed domain model and state lifecycles for SlipItIn games, rounds, phrase decks, players, and challenges.
|
|
tags: [domain, models, state-machine, entity-framework, privacy]
|
|
---
|
|
|
|
# Game Domain & State Models
|
|
|
|
This page describes the core domain entities, relational schema, state machines, and data transfer objects (DTOs) that form the foundation of the SlipItIn game engine.
|
|
|
|
The domain model [is secured by data privacy models defined in](/openwiki/architecture/overview.md) the system architecture, [defines state lifecycles executed by](/openwiki/workflows/slip-and-challenge.md) real-time game workflows, and [maps domain classes in C# project files indexed in](/openwiki/source-map.md) the source map (`SlipItIn.Shared/Models/` and `SlipItIn.Shared/DTOs/`).
|
|
|
|
---
|
|
|
|
## 1. Entity Relationship Diagram (ERD)
|
|
|
|
The database schema is managed via Entity Framework Core (`SlipItInDbContext`) targeting PostgreSQL.
|
|
|
|
```mermaid
|
|
erDiagram
|
|
User {
|
|
int Id PK
|
|
string Username
|
|
string Email
|
|
string PasswordHash
|
|
bool IsActive
|
|
}
|
|
Game {
|
|
int Id PK
|
|
string LobbyCode
|
|
int HostId FK
|
|
GameStatus Status
|
|
int MaxPlayers
|
|
int RoundDurationSeconds
|
|
}
|
|
Player {
|
|
int Id PK
|
|
int UserId FK
|
|
int GameId FK
|
|
int Score
|
|
bool IsReady
|
|
string ConnectionId
|
|
}
|
|
Phrase {
|
|
int Id PK
|
|
string Text
|
|
int CreatorId FK
|
|
bool IsActive
|
|
}
|
|
GameRound {
|
|
int Id PK
|
|
int GameId FK
|
|
int RoundNumber
|
|
RoundStatus Status
|
|
}
|
|
PlayerCard {
|
|
int Id PK
|
|
int PlayerId FK
|
|
int PhraseId FK
|
|
int GameRoundId FK
|
|
bool IsUsed
|
|
}
|
|
SlipChallenge {
|
|
int Id PK
|
|
int GameRoundId FK
|
|
int ChallengingPlayerId FK
|
|
int TargetPlayerId FK
|
|
int TargetCardId FK
|
|
ChallengeStatus Status
|
|
}
|
|
|
|
User ||--o{ Game : "hosts"
|
|
User ||--o{ Player : "participates as"
|
|
User ||--o{ Phrase : "creates"
|
|
Game ||--o{ Player : "contains"
|
|
Game ||--o{ GameRound : "has"
|
|
Player ||--o{ PlayerCard : "holds"
|
|
Phrase ||--o{ PlayerCard : "used in"
|
|
GameRound ||--o{ PlayerCard : "active in"
|
|
GameRound ||--o{ SlipChallenge : "contains"
|
|
Player ||--o{ SlipChallenge : "challenges"
|
|
Player ||--o{ SlipChallenge : "target of"
|
|
PlayerCard ||--o{ SlipChallenge : "targeted by"
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Core Domain Entities (`SlipItIn.Shared/Models`)
|
|
|
|
### `User`
|
|
Represents an authenticated account.
|
|
* **Properties**: `Id`, `Username`, `Email`, `PasswordHash` (BCrypt), `CreatedAt`, `IsActive`.
|
|
* **Relations**: Navigation properties to created `Game` instances, player entries (`Players`), and created phrases (`Phrases`).
|
|
|
|
### `Game`
|
|
Represents a multiplayer game session / lobby.
|
|
* **Properties**: `Id`, `LobbyCode` (6-char alphanumeric), `HostId`, `Status` (`GameStatus`), `CreatedAt`, `StartedAt`, `EndedAt`, `MaxPlayers` (default 8), `RoundDurationSeconds` (30-60s).
|
|
* **Relations**: `Host` (`User`), `Players` (`ICollection<Player>`), `Rounds` (`ICollection<GameRound>`).
|
|
|
|
### `Player`
|
|
Represents a user's participation inside a specific `Game`.
|
|
* **Properties**: `Id`, `UserId`, `GameId`, `Score`, `SuccessfulSlips`, `FailedSlips`, `JoinedAt`, `IsReady`, `ConnectionId` (active SignalR connection ID).
|
|
* **Relations**: `User`, `Game`, `Cards` (`ICollection<PlayerCard>`).
|
|
|
|
### `Phrase`
|
|
Represents a secret phrase or sentence created for the game deck.
|
|
* **Properties**: `Id`, `Text`, `CreatorId`, `CreatedAt`, `IsActive`.
|
|
* **Relations**: `Creator` (`User`), `PlayerCards` (`ICollection<PlayerCard>`).
|
|
|
|
### `GameRound`
|
|
Tracks a distinct round within a game.
|
|
* **Properties**: `Id`, `GameId`, `RoundNumber`, `Status` (`RoundStatus`), `StartedAt`, `EndedAt`.
|
|
* **Relations**: `Game`, `ActiveCards` (`ICollection<PlayerCard>`), `Challenges` (`ICollection<SlipChallenge>`).
|
|
|
|
### `PlayerCard`
|
|
Represents a specific phrase card dealt to a player for a round.
|
|
* **Properties**: `Id`, `PlayerId`, `PhraseId`, `GameRoundId`, `IsUsed` (boolean flag set when player submits slip), `AssignedAt`.
|
|
* **Relations**: `Player`, `Phrase`, `GameRound`.
|
|
|
|
### `SlipChallenge`
|
|
Represents an accusation made by one player against another player's submitted slip.
|
|
* **Properties**: `Id`, `GameRoundId`, `ChallengingPlayerId`, `TargetPlayerId`, `TargetCardId`, `Status` (`ChallengeStatus`), `CreatedAt`, `ResolvedAt`.
|
|
* **Relations**: `GameRound`, `ChallengingPlayer`, `TargetPlayer`, `TargetCard`.
|
|
|
|
---
|
|
|
|
## 3. Enumerations & State Lifecycles
|
|
|
|
### Game Status (`GameStatus`)
|
|
```mermaid
|
|
stateDiagram-v2
|
|
[*] --> Lobby: CreateGameAsync()
|
|
Lobby --> InProgress: StartGameAsync() (Host only)
|
|
InProgress --> Completed: All rounds finished
|
|
Lobby --> Cancelled: Host cancels
|
|
InProgress --> Cancelled: Session abort
|
|
```
|
|
|
|
* **`Lobby`**: Waiting for players to join and set ready status.
|
|
* **`InProgress`**: Active gameplay with dealt cards and active rounds.
|
|
* **`Completed`**: Game finished, final scores tallied.
|
|
* **`Cancelled`**: Lobby or game terminated early.
|
|
|
|
### Round Status (`RoundStatus`)
|
|
```mermaid
|
|
stateDiagram-v2
|
|
[*] --> Waiting: StartGame / New Round
|
|
Waiting --> Active: DealCardsAsync()
|
|
Active --> Resolving: Challenge submitted
|
|
Resolving --> Active: Challenge resolved
|
|
Active --> Completed: Timer expires / All phrases used
|
|
```
|
|
|
|
### Challenge Status (`ChallengeStatus`)
|
|
* **`Pending`**: Accusation registered, awaiting response from the accused player.
|
|
* **`Approved`**: Accusation confirmed (the phrase was indeed an invalid slip). The card remains with the accused player.
|
|
* **`Rejected`**: Accusation rejected (the slip was legitimate). As a penalty, the card is transferred to the accuser's hand (`PlayerCard.PlayerId = ChallengingPlayerId`).
|
|
|
|
---
|
|
|
|
## 4. Data Transfer Objects (DTOs) & Data Privacy
|
|
|
|
To enforce security and data privacy ([Architecture Overview](/openwiki/architecture/overview.md)), the backend exposes decoupled DTOs in `SlipItIn.Shared/DTOs`:
|
|
|
|
| DTO | Visibility | Purpose & Content |
|
|
|---|---|---|
|
|
| `AuthResponseDto` | Direct REST | JWT Access Token, Expiration, Username, Email. |
|
|
| `GameStateDto` | Broadcast (Group) | Public lobby/game status: `GameId`, `LobbyCode`, `Status`, `CurrentRound`, `RoundTimeRemaining`, `Players` (`PlayerInfoDto` array containing `PlayerId`, `Username`, `Score`, `IsReady`, and `CardCount`). **No card text.** |
|
|
| `PlayerHandDto` | Unicast (Client) | Private hand data sent strictly to the card owner: `PlayerId`, `Cards` (`PlayerCardDto` array containing `CardId`, `PhraseId`, `Text`, `IsUsed`). |
|
|
| `SlipChallengeDto` | Unicast / Group | Challenge notification: `ChallengeId`, `ChallengingPlayerId`, `TargetPlayerId`, `TargetCardId`, `Status`, `CreatedAt`. |
|