@startuml !include style.ipuml ' !include hide-groups.ipuml ' !include hide-details.ipuml class main as "main()" hide main circle hide main members exception Exception { + Exception(const char* fmt, ...) + what() : const char* -- # error : char* # va_format(va_list args, const char* fmt) } together { /' LAYOUT '/ rectangle Group_FileReading as "File reading" <> { class FileReader <> { +open(url) : FileStrategy& } interface FileStrategy { + read() : string + close() -- # open(string url) # clone() : FileStrategy* <> } class LocalFile { - instance : LocalFile <> } class HTTPFile { - instance : HTTPFile <> } package CPR { } FileStrategy <|.u. LocalFile FileStrategy <|.u. HTTPFile FileStrategy .l> FileReader FileStrategy <. FileReader HTTPFile -l> CPR ' LAYOUT HTTPFile -r[hidden] LocalFile } rectangle Group_ParsingDeserialization as "Parsing & deserialization" <> { class Parser { + parse(FileStrategy &, Deserializer &) <> + register_strategy(ParserStrategy *) <> -- - get_collection() : ParserCollection <> } interface ParserStrategy { + parse(FileStrategy &, Deserializer &) <> + heuristic(FileStrategy &) : unsigned int <> } ParserStrategy .> Parser ParserStrategy <. Parser class CSVParser class XMLParser class TXTParser package pugixml { } CSVParser ..|> ParserStrategy TXTParser ..|> ParserStrategy XMLParser ..|> ParserStrategy XMLParser -> pugixml class Deserializer { + Deserializer(Museum &) -- + set_canvas(CanvasData) + set_tile(TileData) + add_artist(ArtistData) + add_type(type : string, Color, weight : unsigned int) } CSVParser -up-> Deserializer XMLParser -up-> Deserializer TXTParser -up-> Deserializer ' LAYOUT CSVParser -r[hidden] TXTParser TXTParser -r[hidden] XMLParser } } /' LAYOUT '/ together { /' LAYOUT '/ rectangle Group_Algorithms as "Algorithms" <> { class Pathfinding { + Pathfinding(Museum &) } class Collision { + Collision(Museum &) } } rectangle Group_Model as "Model" <> { class Museum { + people : People + canvas : Canvas -- + update() -- - paused : bool <<+get>> <<+set>> - jump : unsigned long -- - working : bool - worker : thread * - work() } class Canvas { + Canvas(Museum &) -- + get_tile(x, y) : Tile & + set_tile(TileData) -- + update() + data : CanvasData + set_data(CanvasData) -- - tiles : vector - museum : Museum & } class People { + People(Museum &) -- + add_artist(ArtistData) + remove_artist(Artist &) + get_artists() : forward_list -- - artists : forward_list - artist_count : size_t - museum : Museum & } class Tile { + data : TileData + color : Color + behavior : uniq + set_data(TileData &) + set_type(type : const string &) + update() + step(Artist *) + get_neighbor(dx, dy) : Tile * -- - museum : Museum & } struct TileData { + x : unsigned int + y : unsigned int + type : string } class Artist { + update() + step : bool + color : Color + data : ArtistData -- - data : ArtistData - museum : Museum & } struct ArtistData { + x : float + y : float + vx : float + vy : float } struct CanvasData { + rows : unsigned int + columns : unsigned int } Museum --> People Museum --> Canvas Canvas --> Tile People --> Artist Tile -> TileData Artist -l> ArtistData Canvas -> CanvasData ' LAYOUT Artist -r[hidden] Tile } rectangle Group_TileAppearance as "Tile appearance" <> { struct Color { red : unsigned int green : unsigned int blue : unsigned int } class TileAppearance { + get_color(string) : Color <> + register_color(string, Color) <> } Tile --> Color Color <.. TileAppearance } rectangle Group_TileBehavior as "Tile behavior" <> { interface TileBehaviorStrategy { + step(Artist *) + update(Tile &) + clone(Museum &) : uniq -- # TileBehaviorStrategy(type : string) # TileBehaviorStrategy() -- # interactions : unsigned int # museum : Museum * } class TileBehavior { + get_strategy(string) : TileBehaviorStrategy & <> + register_strategy(string, TileBehaviorStrategy *) <> -- - get_collection() : TileBehaviorCollection & <> } together { class NullTileBehavior { - type = "" <> } class GrayTileBehavior { - type = "G" : <> } class RedTileBehavior { - type = "R" : <> } class BlueTileBehavior { - type = "B" : <> -- - dx : int - dy : int } class YellowTileBehavior { - type = "Y" : <> -- - last_interactions : unsigned int } } TileBehaviorStrategy <|.. NullTileBehavior TileBehaviorStrategy <|.. GrayTileBehavior TileBehaviorStrategy <|.. RedTileBehavior TileBehaviorStrategy <|.. BlueTileBehavior TileBehaviorStrategy <|.. YellowTileBehavior Tile --> "state" TileBehavior TileBehavior .l> TileBehaviorStrategy TileBehavior <. TileBehaviorStrategy } } /' LAYOUT '/ together { /' LAYOUT '/ rectangle Group_Visualization as "Visualization" <> { struct Rectangle { x : unsigned int y : unsigned int width : unsigned int height : unsigned int } enum MouseCode { } enum KeyboardCode { } package SDL3 { } class View { + window_size(width, height) + dialog_file(callback : fn(files : vec, data), data) + draw_rect(Rectangle, Color) -- - window : SDL_Window * - renderer : SDL_Renderer * -- + open : bool - worker : thread * - work() } class ViewController { + update() + ev_keydown(KeyboardCode); + ev_mousedown(MouseCode); + ev_mousemove(x, y); -- - draw_artists : bool <<+get>> <<+set>> - cmd_base : const Command * } ViewController ..> View ViewController <-- View View --> SDL3 View .l> Rectangle ViewController .l> KeyboardCode ViewController .l> MouseCode } rectangle Group_Commands as "Commands" <> { class Command { # museum : Museum * <<+get&>> <<-set>> # view : View * <<+get&>> <<-set>> # controller : ViewController * <<+get&>> <<-set>> -- + Command(command : const Command *) + Command(museum, view, controller) } class MuseumPauseCommand { + toggle() + set(paused : bool) } class OpenFileGUICommand { + execute() } class ArtistVisibilityCommand { + toggle() + set(paused : bool) } class LoadFilesCommand { + execute(files) } class TileDecayCommand { + execute(x, y) } Command <|-u- MuseumPauseCommand Command <|-u- OpenFileGUICommand Command <|-u- ArtistVisibilityCommand Command <|-u- TileDecayCommand Command <|-d- LoadFilesCommand } } /' LAYOUT '/ Command .[norank]> Museum Command .[norank]> View Command .[norank]> ViewController ParserStrategy .l> FileStrategy Deserializer .l> Museum Museum --> Pathfinding Museum --> Collision ViewController -[norank]> Command main -d-> Museum main -u-> LoadFilesCommand ' main -[norank]> Deserializer main -[norank]> View main .r> Exception ' LAYOUT Group_TileBehavior -r[hidden] Group_TileAppearance Group_ParsingDeserialization -r[hidden] Group_Model ' Collision -r[hidden] People @enduml