#pragma once #include #include #include #include #include #include #include #include #include #include "spdlog/spdlog.h" namespace commons { static constexpr size_t screen_size = 30; namespace protocol { struct vec2; struct pixel; } // namespace protocol class render_interface { public: virtual ~render_interface() = default; virtual void update_pixel(commons::protocol::vec2 position, commons::protocol::pixel pixel) = 0; virtual void draw() = 0; }; namespace protocol { enum class Type { DRAW_RECTANGLE = 0, DRAW_PIXEL, }; class generic_message_base : std::enable_shared_from_this { public: virtual ~generic_message_base() { spdlog::debug("base dtor"); } virtual constexpr Type get_type() const = 0; virtual uint32_t get_size() const = 0; auto get_shared_ptr() { return shared_from_this(); } auto serialize() const { const auto* void_ptr = reinterpret_cast(this); return boost::asio::buffer(void_ptr, get_size()); } virtual void operator()() { if (is_handler) { handle_message(); return; } create_message(); } virtual void handle_message() = 0; virtual void handle_message(render_interface* renderer){}; virtual void create_message() { spdlog::debug("create_message is not implemented yet"); } virtual void handle_sent(const boost::system::error_code& er) { if (!er) { spdlog::debug("Message was sent"); } else { spdlog::error("Error occured on client::send"); } } protected: bool is_handler = true; }; class draw_rectangle; template class generic_message : public generic_message_base { public: virtual ~generic_message() = default; virtual constexpr Type get_type() const override { return type_; } protected: static constexpr Type type_ = TypeValue; }; inline std::unique_ptr deserialize( char* buffer, std::size_t object_size) { void* base_ptr = std::malloc(object_size); std::memcpy(base_ptr, buffer, object_size); return std::unique_ptr( reinterpret_cast(base_ptr)); } struct vec2 { int x, y; }; struct vec3 { int x, y, z; }; enum class background_color { BLACK = 40, RED, GREEN, YELlOW, BLUE, MAGENTA, CYAN, WHITE, }; enum class foreground_color { BLACK = 30, RED, GREEN, YELlOW, BLUE, MAGENTA, CYAN, WHITE, }; struct pixel { char value = '#'; foreground_color color_fg = foreground_color::GREEN; background_color color_bg = background_color::BLACK; }; class draw_rectangle : public generic_message { public: virtual ~draw_rectangle() { spdlog::debug("draw_rect dtor"); } virtual uint32_t get_size() const override { return sizeof(*this); } virtual void handle_message() override { spdlog::debug("draw_rectangle::handle_message()"); spdlog::debug("Position: X = {}, Y = {}", position.x, position.y); spdlog::debug("handle_message sleeps for 1 sec to test concurrency"); std::this_thread::sleep_for(std::chrono::seconds(1)); } vec2 position; vec2 size; vec3 color; }; class draw_pixel : public generic_message { public: virtual ~draw_pixel() { spdlog::debug("draw_pixel dtor"); } virtual uint32_t get_size() const override { return sizeof(*this); } virtual void handle_message() override { spdlog::debug("draw_pixel::handle_message()"); spdlog::debug("Color: ({}, {}, {})", color.x, color.y, color.z); spdlog::debug("handle_message sleeps for 1 sec to test concurrency"); std::this_thread::sleep_for(std::chrono::seconds(1)); } virtual void handle_message(render_interface* renderer) override { renderer->update_pixel(position, pixel_); } vec2 position; pixel pixel_; vec3 color; }; class Serializer {}; } // namespace protocol class cli_renderer : public render_interface { public: cli_renderer(size_t screen_size) : screen{screen_size, std::vector{screen_size}} {} virtual ~cli_renderer() = default; virtual void update_pixel(commons::protocol::vec2 position, commons::protocol::pixel pixel) override { screen[position.y][position.x] = pixel; draw(); } virtual void draw() override { std::stringstream str; for (const auto& row : screen) { for (const auto& pixel : row) { str << "\033[" << static_cast(pixel.color_fg) << ";" << static_cast(pixel.color_bg) << "m" << pixel.value; } str << "\033[30;40m\n"; } str << "\033[30;40m\n"; std::cout << str.str() << '\n'; } private: std::vector> screen; }; } // namespace commons