diff --git a/diagrams/class_diagram.puml b/diagrams/class_diagram.puml deleted file mode 100644 index c3d8f06..0000000 --- a/diagrams/class_diagram.puml +++ /dev/null @@ -1,158 +0,0 @@ -@startuml BeatBattle_ClassDiagram -skinparam classAttributeIconSize 0 -skinparam packageStyle rectangle -skinparam linetype ortho -skinparam padding 5 -skinparam nodesep 40 -skinparam ranksep 60 -hide members -hide circle - -title BeatBattle — Class Diagram (Current Architecture) - -' ─── EXTERNAL ─── -package "External" { - interface "Firebase\n(Firestore)" as Firebase -} - -' ─── VIEW ─── -package "View" { - class SettingsView - class StartView - class JoinCreateView - class LobbyView - class GameRoundView - class LeaderboardView - class GameOverView -} - -' ─── STATES ─── -package "States" { - abstract class State <> - class StateManager - - class StartState - class JoinCreateState - class LobbyState - class InRoundState - class LeaderboardState - class GameOverState - class SettingsState - - StartState --|> State - JoinCreateState --|> State - LobbyState --|> State - InRoundState --|> State - LeaderboardState --|> State - GameOverState --|> State - SettingsState --|> State - - StateManager --> State -} - -' ─── CONTROLLER ─── -package "Controller" { - class RoundController - class LeaderboardController - class LobbyController - class SettingsController -} - -' ─── MODEL ─── -package "Model" { - - package "Services" { - interface FirebaseGateway - class LobbyService - class QuestionBuilder - class SessionSyncService - class ScoreCalculator - interface MusicService - - LobbyService --> FirebaseGateway - QuestionBuilder --> FirebaseGateway - SessionSyncService --> FirebaseGateway - } - - package "Domain" { - class GameSession - class Player - class Question - class Song - class AnswerSubmission - class Leaderboard - class LeaderboardEntry - - GameSession *-- Player - GameSession *-- Question - Question *-- Song - Leaderboard *-- LeaderboardEntry - } -} - -' ─── ECS ─── -package "ECS" { - class Engine - class RoundManager - class Entity - - abstract class EntitySystem <> - class AudioSystem - class RoundSystem - - interface Component - class AudioComponent - class TimerComponent - - AudioSystem --|> EntitySystem - RoundSystem --|> EntitySystem - AudioComponent ..|> Component - TimerComponent ..|> Component - Entity *-- Component - Engine *-- Entity - Engine *-- EntitySystem - RoundManager --> Engine -} - -' ─── PLATFORM ─── -package "Platform" { - package "Android" { - class AndroidLauncher - class AndroidFirebaseGateway - class AndroidAudioPlayer - class DeezerMusicService - class FirestoreSessionRepository - - AndroidFirebaseGateway ..|> FirebaseGateway - AndroidFirebaseGateway --> FirestoreSessionRepository - DeezerMusicService ..|> MusicService - } - package "Desktop" { - class Lwjgl3Launcher - class NoOpFirebaseGateway - class MockMusicService - - NoOpFirebaseGateway ..|> FirebaseGateway - MockMusicService ..|> MusicService - } -} - -' ─── CROSS-PACKAGE RELATIONSHIPS ─── -FirebaseGateway ..> Firebase : uses - -State --> "Controller" -State --> "View" - -LobbyController --> LobbyService -LobbyController --> MusicService -LobbyController --> QuestionBuilder -LobbyController --> SessionSyncService - -RoundController --> RoundManager -RoundController --> ScoreCalculator -RoundController --> FirebaseGateway - -LeaderboardController --> FirebaseGateway -LeaderboardController --> GameSession - -@enduml diff --git a/diagrams/ecs_diagram.puml b/diagrams/ecs_diagram.puml deleted file mode 100644 index 8e46c52..0000000 --- a/diagrams/ecs_diagram.puml +++ /dev/null @@ -1,184 +0,0 @@ -@startuml BeatBattle_ECS_Diagram -skinparam classAttributeIconSize 0 -skinparam packageStyle rectangle -skinparam linetype ortho -hide empty members - -title BeatBattle — Entity Component System (ECS) - -' ───────────────────────────────────────── -' COMPONENT LAYER -' ───────────────────────────────────────── -package "Components" { - interface Component <> - - class AudioComponent { - +previewUrl: String - +isPlaying: boolean - } - - class TimerComponent { - +timeRemaining: float - +totalTime: float - +expired: boolean - } - - Component <|.. AudioComponent - Component <|.. TimerComponent -} - -' ───────────────────────────────────────── -' ENTITY LAYER -' ───────────────────────────────────────── -package "Entities" { - class Entity { - -components: Map - +addComponent(T extends Component) - +getComponent(Class): T - +hasComponent(Class): boolean - +removeComponent(Class) - +removeAll() - } - - class RoundFactory <> { - +createRound(url: String,\n duration: float,\n audioPlayer: AudioPlayer): Entity - } - - Entity "1" *-- "0..*" Component : stores - RoundFactory ..> Entity : creates - RoundFactory ..> AudioComponent : attaches - RoundFactory ..> TimerComponent : attaches -} - -' ───────────────────────────────────────── -' SYSTEM LAYER -' ───────────────────────────────────────── -package "Systems" { - abstract class EntitySystem { - +{abstract} update(entities: List, delta: float) - } - - class AudioSystem <> { - -audioPlayer: AudioPlayer - -muted: boolean - +play(entity: Entity) - +stop(entity: Entity) - +stopAll() - +setMuted(boolean) - +isMuted(): boolean - +update(entities, delta) - } - - class RoundSystem <> { - -listener: RoundExpiredListener - +update(entities: List, delta: float) - ' decrements TimerComponent.timeRemaining each frame - ' fires listener when timeRemaining <= 0 - } - - interface "RoundSystem.RoundExpiredListener" as RoundExpiredListener { - +onRoundExpired() - } - - EntitySystem <|-- AudioSystem - EntitySystem <|-- RoundSystem - RoundSystem --> RoundExpiredListener : fires - AudioSystem --> AudioComponent : reads/writes - RoundSystem --> TimerComponent : updates -} - -' ───────────────────────────────────────── -' ENGINE -' ───────────────────────────────────────── -package "Engine" { - class Engine <> { - -entities: List - -systems: List - +addEntity(Entity) - +removeEntity(Entity) - +addSystem(EntitySystem) - +removeSystem(EntitySystem) - +update(delta: float) - +reset() - } - - Engine "1" *-- "0..*" Entity : manages - Engine "1" *-- "0..*" EntitySystem : runs -} - -' ───────────────────────────────────────── -' FACADE -' ───────────────────────────────────────── -package "Facade" { - class RoundManager { - -entity: Entity - -engine: Engine - -audioSystem: AudioSystem - -roundSystem: RoundSystem - +getTimeRemaining(): float - +getTotalTime(): float - +stop() - +isMuted(): boolean - +setMuted(boolean) - } - - RoundManager --> Engine : uses - RoundManager --> RoundFactory : uses to create entity - RoundManager --> AudioSystem : delegates audio calls - RoundManager --> RoundSystem : delegates timer calls -} - -' ───────────────────────────────────────── -' AUDIO INTERFACE -' ───────────────────────────────────────── -package "Audio" { - interface AudioPlayer { - +play(url: String) - +stop() - +setMuted(boolean) - +dispose() - } -} - -AudioSystem --> AudioPlayer : plays via - -' ───────────────────────────────────────── -' CONTROLLER INTEGRATION -' ───────────────────────────────────────── -package "Controller" { - class RoundController { - -roundManager: RoundManager - +update(delta: float) - +onAnswerSubmitted(answer: String) - +onRoundExpired() - +getTimeRemaining(): float - +setMuted(boolean) - } - class BeatBattle { - +create() - ' initialises Engine, adds AudioSystem & RoundSystem - } -} - -RoundController --> RoundManager : owns / delegates -BeatBattle --> Engine : owns & initialises -RoundController ..|> RoundExpiredListener : implements - -note bottom of RoundManager - Facade over ECS: - Controllers never touch Engine, - Entity, or raw Components. - RoundManager hides ECS complexity. -end note - -note right of Engine - Update loop per frame: - for each system: - system.update(entities, delta) - AudioSystem is event-driven - (play/stop calls, not per-tick). - RoundSystem decrements timer - every frame. -end note - -@enduml