127 lines
7.3 KiB
Markdown
127 lines
7.3 KiB
Markdown
# RpgRoller
|
|
|
|
Fresh full-stack starter scaffold:
|
|
|
|
- `RpgRoller/`: ASP.NET Core backend + Blazor frontend host (`Components` + `wwwroot`)
|
|
- `RpgRoller.Tests/`: xUnit integration-heavy test project
|
|
- `RpgRoller.sln`: solution used by local CI script
|
|
|
|
Test layout:
|
|
|
|
- `RpgRoller.Tests/Api/`: API integration tests grouped by feature concern
|
|
- `RpgRoller.Tests/Services/`: service-level tests grouped by domain concern
|
|
- `RpgRoller.Tests/Support/`: shared test harnesses/builders/helpers
|
|
|
|
## Code Organization
|
|
|
|
Backend:
|
|
|
|
- `RpgRoller/Program.cs`: thin app bootstrap only
|
|
- `RpgRoller/Hosting/`: service registration + startup initialization
|
|
- `RpgRoller/Api/`: endpoint mapping modules and auth/session filter helpers
|
|
- `RpgRoller/Services/`: game workflows with explicit method parameters (no API DTO dependencies)
|
|
|
|
Frontend:
|
|
|
|
- `RpgRoller/Components/`: Blazor root app, routes, layout and page components
|
|
- `RpgRoller/Components/Pages/Home.razor`: minimal gateway page (loading/auth/workspace switch)
|
|
- `RpgRoller/Components/Pages/Home.razor.cs`: single `Home` code-behind with only gateway/session-view orchestration
|
|
- `RpgRoller/Components/Pages/Workspace.razor`: authenticated workspace UI and workspace-specific state/logic
|
|
- `RpgRoller/Components/**/*.razor.cs`: component code-behind classes (state, handlers, parameters, injected dependencies); `.razor` files remain markup-focused
|
|
- `RpgRoller/Components/Pages/Home.Models.cs`: reusable `FormState<TModel>` + page form models
|
|
- `RpgRoller/Components/Pages/HomeControls/`: auth, campaign management, play-screen, and modal controls extracted from `Home.razor`
|
|
- Form ownership model: controls own transient form/error state and execute their concern-specific API mutations directly
|
|
- Skill create/edit workflow ownership: `CharacterPanel` (characters own skills in UI and behavior)
|
|
- `RpgRoller/Components/RpgRollerApiClient.cs`: shared browser API client used by `Home`, `Workspace`, and leaf controls
|
|
- `RpgRoller/wwwroot/js/rpgroller-api.js`: browser-side API + SSE + session storage interop for Blazor
|
|
- `RpgRoller/wwwroot/styles.css`: responsive UX styling and theme tokens
|
|
|
|
Backend state persistence:
|
|
|
|
- EF Core with SQLite (`Microsoft.EntityFrameworkCore.Sqlite`)
|
|
- Development DB: `RpgRoller/App_Data/rpgroller.development.db`
|
|
- Default DB: `RpgRoller/App_Data/rpgroller.db`
|
|
- Database schema is created/upgraded automatically on startup via EF Core migrations (`Database.Migrate`)
|
|
- Runtime state is loaded once at startup into memory and written back to SQLite on successful state changes
|
|
|
|
Gameplay capabilities now include:
|
|
|
|
- Instant skill filtering in the character panel (filters live while typing and hides non-matching skills/groups)
|
|
- Supported campaign rulesets include D6 System, D&D 5e, and Rolemaster
|
|
- Skill groups per character with skill prototypes (create/edit/delete groups, assign/reassign skills, and prefill new skill forms from group defaults)
|
|
- Skill and skill-group deletion flows
|
|
- GM-driven character owner transfer within campaign management flows
|
|
- Character owner selection in edit modal backed by existing-username dropdown data
|
|
- Role-aware authorization with admin role support (including admin user/role management)
|
|
- Admin workspace tools include direct download of the live SQLite database file
|
|
- Campaign deletion by campaign owner or admin (unlinks characters from the campaign and clears campaign log entries)
|
|
- User deletion by admin also deletes campaigns owned by that user and unlinks all characters from those deleted campaigns
|
|
- Play screen visibility is owner-scoped: only owned characters are listed, and private log entries are visible only to the roller
|
|
- Campaign management owner labels use account display names (no GUID fallback rendering)
|
|
- Character edit flow supports unlinking from campaigns (owner/GM/admin) and assigning to any existing campaign via expanded campaign options
|
|
- Campaign management supports character deletion by character owner or admin
|
|
- Shared top header control across all authenticated workspace screens (play, campaign management, admin)
|
|
- Admin user management is integrated into workspace screen toggles (`Play`, `Campaign Management`, `Admin`)
|
|
- Rolemaster expression validation currently recognizes `2d10+48`, `d100+4`, and `d100!+85`, including Rolemaster-only negative modifiers such as `d100-15`
|
|
- Rolemaster open-ended percentile skills and skill-group defaults now persist a nullable `FumbleRange` field, while D6 and D&D rows migrate forward unchanged
|
|
- Startup migration coverage is validated against a copied temp-file instance of `RpgRoller/App_Data/rpgroller.development.db` before feature work is considered complete
|
|
|
|
## Prerequisites
|
|
|
|
- .NET SDK 10.0+
|
|
- PowerShell 7+
|
|
- Run `dotnet tool restore` once to enable the repo-local `dotnet-ef` command.
|
|
|
|
## Local Development
|
|
|
|
1. Run the local CI parity script:
|
|
```powershell
|
|
pwsh ./scripts/ci-local.ps1
|
|
```
|
|
2. Start the backend:
|
|
```powershell
|
|
dotnet run --project RpgRoller/RpgRoller.csproj
|
|
```
|
|
3. Open `http://localhost:5000` (or the port shown in the console).
|
|
|
|
VS Code F5 debug profiles are available in `.vscode/launch.json`:
|
|
|
|
- `RpgRoller: Server`
|
|
- `RpgRoller: Server + Edge (F5)`
|
|
- `RpgRoller: Server + Firefox (F5)`
|
|
|
|
To use a custom SQLite database path, set `ConnectionStrings__RpgRoller`.
|
|
To run under a subfolder (for example `/rpgroller`), set `PathBase` (for example `PathBase=/rpgroller`).
|
|
|
|
For migration authoring, use the local tool command form:
|
|
|
|
```powershell
|
|
dotnet dotnet-ef migrations add <MigrationName> --project RpgRoller/RpgRoller.csproj --startup-project RpgRoller/RpgRoller.csproj
|
|
```
|
|
|
|
## Frontend Runtime
|
|
|
|
- Runtime frontend is Blazor Server with interactive components.
|
|
- Browser interop is in `RpgRoller/wwwroot/js/rpgroller-api.js`.
|
|
- Root static assets such as `styles.css` are linked through Blazor's `@Assets[...]` pipeline so deploys get fingerprinted cache-busting URLs automatically.
|
|
- Workspace reads are resolved server-side through scoped query services; browser interop remains for browser-only concerns such as session storage, SSE wiring, and DOM helpers.
|
|
- Live workspace refreshes now compare separate roster, per-character sheet, and log versions so unrelated state changes do not force a full roster + sheet + log reload.
|
|
- Workspace campaign data is loaded in bounded slices: visible campaign summaries, a selected campaign roster, a selected character sheet, and a 25-row incremental log window backed by `/api/campaigns/{campaignId}/log/page`.
|
|
- Campaign log rows now ship compact summary data first and lazy-load dice + breakdown detail through `/api/rolls/{rollId}` only when a row is expanded.
|
|
- Hot API contracts share a source-generated `System.Text.Json` context, and HTTP JSON responses are gzip-compressed when the client advertises support.
|
|
- OpenAPI contract source remains at `openapi/RpgRoller.json`.
|
|
|
|
## Test and Coverage
|
|
|
|
- Tests:
|
|
```powershell
|
|
dotnet test RpgRoller.Tests/RpgRoller.Tests.csproj --collect:"XPlat Code Coverage" --settings RpgRoller.Tests/coverlet.runsettings
|
|
```
|
|
- Regression tests enforce payload budgets for the hottest contracts: character sheet reads, initial log page loads, incremental log updates, and roll mutation responses.
|
|
- Coverage gate:
|
|
```powershell
|
|
pwsh ./scripts/check-coverage.ps1 -MinLineRate 0.90 -MinBranchRate 0.70
|
|
```
|
|
- Coverage collector scope:
|
|
- `RpgRoller.Tests/coverlet.runsettings` now measures the full backend assembly (`RpgRoller`), not only service namespace files.
|