@startuml





/' Objects '/

namespace flippR_driver::output::items {
	class Display <template<int DigitCount>> {
		+Display(int address, int id)
		+~Display()
		-address : int
		+content : std::array<char, DigitCount>
		-fit_string(std::string& score_string) : std::string
		+get_content() : std::vector<char>
		+write_content(std::array<char, DigitCount> content) : void
		+write_score(int score) : void
	}
}


namespace flippR_driver::output {
	class DisplayController {
		+DisplayController(std::vector<std::shared_ptr<items::IDisplay> > displays, std::shared_ptr<utility::IOutputGPIOInterface> pin_controller)
		+~DisplayController()
		-is_running : bool
		-pin_controller : std::shared_ptr<utility::IOutputGPIOInterface>
		-display_cycle_thread : std::thread
		-displays : std::vector<std::shared_ptr<items::IDisplay> >
		-cycle_displays() : void
	}
}


namespace flippR_driver::utility {
	class DisplayGPIOInterface {
		+DisplayGPIOInterface()
		+~DisplayGPIOInterface()
	}
}


namespace flippR_driver::utility {
	class GPIOInterface {
		+GPIOInterface()
		+~GPIOInterface()
		#{static} read_pin(char address) : bool
		+{static} GPIO_LIB_INITIALIZED : static std::once_flag
		-pin_base : unsigned int
		#{static} initialize_input_pin(char address) : void
		#{static} initialize_output_pin(char address) : void
		#{static} write_pin(char address, char data) : void
	}
}


namespace flippR_driver::utility {
	abstract class IBlockingQueue <template<typename T>> {
		+~IBlockingQueue()
		+{abstract} pop() : T
		+{abstract} push(T const& value) : void
	}
}


namespace flippR_driver::output::items {
	abstract class IDisplay {
		+IDisplay()
		+~IDisplay()
		+{abstract} get_content() : std::vector<char>
	}
}


namespace flippR_driver::output {
	class IDisplayController {
		+IDisplayController()
		+~IDisplayController()
	}
}


namespace flippR_driver::output::items {
	class IDriverBoardItem {
		+~IDriverBoardItem()
	}
}


namespace flippR_driver::utility {
	abstract class IInputGPIOInterface {
		+~IInputGPIOInterface()
		+{abstract} read_data(char pin) : bool
	}
}


namespace flippR_driver::output::items {
	abstract class IItem {
		+~IItem()
		+{abstract} get_address() : uint8_t
	}
}


namespace flippR_driver::utility {
	abstract class IOutputGPIOInterface {
		+~IOutputGPIOInterface()
		+{abstract} activate(output::items::IDriverBoardItem* driver_board_item) : void
		+{abstract} activate(output::items::ISoundItem* sound) : void
		+{abstract} deactivate(output::items::IDriverBoardItem* driver_board_item) : void
		+{abstract} deactivate(output::items::ISoundItem* sound) : void
		+{abstract} write_display(std::shared_ptr<output::items::IDisplay> display) : void
	}
}


namespace flippR_driver::output::items {
	class ISoundItem {
	}
}


namespace flippR_driver::utility {
	class InputGPIOInterface {
		+InputGPIOInterface(std::istream& input_config)
		+read_data(char pin) : bool
		-col_address_A : char
		-col_address_B : char
		-col_address_C : char
		-data_address : char
		-row_address_A : char
		-row_address_B : char
		-row_address_C : char
		-init_members(std::istream& input_config_stream) : void
		-init_pins() : void
		-write_col(char data) : void
		-write_row(char data) : void
	}
}


namespace flippR_driver::utility {
	class InputSocketHandler {
		+InputSocketHandler(boost::asio::io_service& service, std::string socket_file)
		-serialize_event(input::Event& event) : nlohmann::json
		+handle(input::Event& event) : void
	}
}


namespace flippR_driver::output::items {
	class Item {
		+Item(std::shared_ptr<utility::IOutputGPIOInterface> pin_controller, uint8_t address, std::string name)
		+~Item()
		#gpio_interface : const std::shared_ptr<utility::IOutputGPIOInterface>
		#name : const std::string
		#address : const uint8_t
		+get_address() : uint8_t
	}
}


namespace flippR_driver::output::items {
	class Lamp {
		+Lamp(std::shared_ptr<utility::IOutputGPIOInterface> pin_controller, uint8_t address, std::string name)
		+~Lamp()
		-activated : bool
		+is_activated() : bool
		+activate() : void
		+deactivate() : void
	}
}


namespace flippR_driver::output {
	class OutputDriver {
		+OutputDriver(std::map<std::string, std::shared_ptr<items::ISolenoid> > solenoids, std::map<std::string, std::shared_ptr<items::ILamp> > lamps, std::map<char, std::shared_ptr<items::IDisplay> > displays, std::map<std::string, std::shared_ptr<items::ISound> > sounds)
		+~OutputDriver()
		-displays : std::map<char, std::shared_ptr<items::IDisplay> >
		-lamps : std::map<std::string, std::shared_ptr<items::ILamp> >
		-solenoids : std::map<std::string, std::shared_ptr<items::ISolenoid> >
		-sounds : std::map<std::string, std::shared_ptr<items::ISound> >
		+get_display(char number) : std::shared_ptr<items::IDisplay>
		+get_lamp(std::string name) : std::shared_ptr<items::ILamp>
		+get_solenoid(std::string name) : std::shared_ptr<items::ISolenoid>
		+get_sound(std::string name) : std::shared_ptr<items::ISound>
		+get_displays() : std::vector<std::shared_ptr<items::IDisplay> >
		+get_lamps() : std::vector<std::shared_ptr<items::ILamp> >
		+get_solenoids() : std::vector<std::shared_ptr<items::ISolenoid> >
		+get_sounds() : std::vector<std::shared_ptr<items::ISound> >
	}
}


namespace flippR_driver::output {
	class OutputDriverFactory {
		+{static} getOutputDriver(std::ifstream& output_gpio_config, std::ifstream& output_config) : std::shared_ptr<OutputDriver>
	}
}


namespace flippR_driver::utility {
	class OutputGPIOInterface {
		+OutputGPIOInterface(std::istream& output_config_stream)
		+~OutputGPIOInterface()
		-pins_display : std::map<std::string, uint8_t>
		-pins_driver_board : std::map<std::string, uint8_t>
		-pins_sound : std::map<std::string, uint8_t>
		-output_item_mutex : std::mutex
		+activate(output::items::IDriverBoardItem* driver_board_item) : void
		+activate(output::items::ISoundItem* sound) : void
		+deactivate(output::items::IDriverBoardItem* driver_board_item) : void
		+deactivate(output::items::ISoundItem* sound) : void
		-fire_sound(bool fire) : void
		-initialize_all_pins(uint8_t pin_base) : void
		-initialize_i2c_addresses() : void
		-initialize_pins() : void
		-parse_output_config(nlohmann::json& output_config) : void
		-parse_pins_display(nlohmann::json& display_board_config) : void
		-parse_pins_driver_board(nlohmann::json& driver_board_config) : void
		-parse_pins_sound(nlohmann::json& sound_board_config) : void
		-select_latch(uint8_t latch) : void
		-select_mux(uint8_t latch) : void
		-select_pin(uint8_t pin) : void
		-write_data(bool data) : void
		+write_display(output::items::IDisplay* display) : void
		-write_driver_board_address(uint8_t address) : void
		-write_sound_address(uint8_t address) : void
	}
}


namespace flippR_driver::utility {
	class SocketHandler {
		+SocketHandler(boost::asio::io_service& service, std::string socket_file)
		#socket : boost::asio::local::stream_protocol::socket
		#write_to_socket(nlohmann::json& data) : void
	}
}


namespace flippR_driver::output::items {
	class Solenoid {
		+Solenoid(std::shared_ptr<utility::IOutputGPIOInterface> pin_controller, u_int8_t address, std::string name, std::chrono::milliseconds deactivation_time)
		+~Solenoid()
		-deactivation_time : std::chrono::milliseconds
		-trigger_task : std::future<void>
		+trigger() : void
		-triggerTask() : void
	}
}


namespace flippR_driver::output::items {
	class Sound {
		+Sound(std::shared_ptr<utility::IOutputGPIOInterface> pin_controller, uint8_t address, std::string name, std::chrono::milliseconds deactivation_time, u_int id)
		+~Sound()
		-deactivation_time : std::chrono::milliseconds
		-play_task : std::future<void>
		+id : u_int
		+play() : void
		-playTask() : void
	}
}





/' Inheritance relationships '/

namespace flippR_driver::utility {
	GPIOInterface <|-- InputGPIOInterface
}


namespace flippR_driver::utility {
	GPIOInterface <|-- OutputGPIOInterface
}


namespace flippR_driver::output::items {
	IDisplay <|-- Display
}


namespace flippR_driver::output {
	IDisplayController <|-- DisplayController
}


namespace flippR_driver::output::items {
	IDriverBoardItem <|-- Lamp
}


namespace flippR_driver::output::items {
	IDriverBoardItem <|-- Solenoid
}


namespace flippR_driver::utility {
	IInputGPIOInterface <|-- InputGPIOInterface
}


namespace flippR_driver::output::items {
	IItem <|-- IDriverBoardItem
}


namespace flippR_driver::output::items {
	IItem <|-- ISoundItem
}


namespace flippR_driver::output::items {
	IItem <|-- Item
}


namespace flippR_driver::utility {
	IOutputGPIOInterface <|-- OutputGPIOInterface
}


namespace flippR_driver::output::items {
	ISoundItem <|-- Sound
}


namespace flippR_driver::output::items {
	Item <|-- Lamp
}


namespace flippR_driver::output::items {
	Item <|-- Solenoid
}


namespace flippR_driver::output::items {
	Item <|-- Sound
}


namespace flippR_driver::utility {
	SocketHandler <|-- InputSocketHandler
}





/' Aggregation relationships '/

flippR_driver::output.DisplayController o-- flippR_driver::output::items.IDisplay


flippR_driver::output.DisplayController o-- flippR_driver::utility.IOutputGPIOInterface


flippR_driver::output::items.Item o-- flippR_driver::utility.IOutputGPIOInterface


flippR_driver::output.OutputDriver o-- flippR_driver::output::items.IDisplay




@enduml
