1. IMediaStorageService (src/Koogle.Domain/Interfaces/):
- Neue Methoden GetMediaBasePath() und GetFilePath() hinzugefügt
2. MediaStorageService (src/Koogle.Infrastructure/Services/):
- Erkennt Production+Linux → verwendet /home/data/club-media
- Development → verwendet wwwroot/club-media
3. Program.cs (src/Koogle.Web/):
- StaticFileOptions für /club-media aus /home/data/club-media in Production
4. DemoSeeder (src/Koogle.Infrastructure/Data/):
- Alle Methoden nutzen jetzt IMediaStorageService statt hardkodierte Pfade
5. ClubGifService (src/Koogle.Application/Services/):
- Alle Path.Combine("wwwroot", ...) durch _mediaStorage.GetFilePath() ersetzt
Das Verhalten:
- Windows/Development: weiterhin wwwroot/club-media
- Linux/Production (Azure): /home/data/club-media (persistent und beschreibbar)
- IGameHubClient: client interface for SignalR messages
- GameHub: SignalR hub with group management for games/days
- GameHubService: scoped service wrapper with auto-reconnect
- GameEffects: broadcasts game start/end/state via SignalR
- EndGameAction: extended with winner info and final scores
- Program.cs: AddSignalR + MapHub configuration
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- TrainingGameDefinition with game type metadata
- TrainingGameModel + TrainingPlayerStats for stats tracking
- TrainingGameLogicService implementing game logic
- TrainingSetup.razor for config (ThrowMode, ThrowsPerRound, ParticipantsMode)
- TrainingBoard.razor showing player stats table with totals/averages
- Game type registration in Program.cs
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>