Files
initiative/specs/018-combatant-concentration/data-model.md

46 lines
1.8 KiB
Markdown

# Data Model: Combatant Concentration
**Feature**: 018-combatant-concentration | **Date**: 2026-03-06
## Entity Changes
### Combatant (modified)
| Field | Type | Required | Default | Notes |
|-------|------|----------|---------|-------|
| id | CombatantId | yes | - | Existing, unchanged |
| name | string | yes | - | Existing, unchanged |
| initiative | number | no | undefined | Existing, unchanged |
| maxHp | number | no | undefined | Existing, unchanged |
| currentHp | number | no | undefined | Existing, unchanged |
| ac | number | no | undefined | Existing, unchanged |
| conditions | ConditionId[] | no | undefined | Existing, unchanged |
| **isConcentrating** | **boolean** | **no** | **undefined (falsy)** | **New field. Independent of conditions.** |
### Domain Events (new)
| Event | Fields | Emitted When |
|-------|--------|-------------|
| ConcentrationStarted | `type`, `combatantId` | Concentration toggled from off to on |
| ConcentrationEnded | `type`, `combatantId` | Concentration toggled from on to off |
## State Transitions
```
toggleConcentration(encounter, combatantId)
├── combatant not found → DomainError("combatant-not-found")
├── isConcentrating is falsy → set to true, emit ConcentrationStarted
└── isConcentrating is true → set to undefined, emit ConcentrationEnded
```
## Validation Rules
- `combatantId` must reference an existing combatant in the encounter.
- No other validation needed (boolean toggle has no invalid input beyond missing combatant).
## Storage Impact
- **Format**: JSON via localStorage (existing adapter).
- **Migration**: None. Field is optional; absent field is treated as `false`.
- **Backward compatibility**: Old data loads without `isConcentrating`; new data with the field serializes/deserializes transparently.