#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 update_rect(commons::protocol::vec2 position, commons::protocol::vec2 width, commons::protocol::pixel pixel) = 0; virtual void draw() = 0; }; namespace protocol { enum class Type { DRAW_RECTANGLE = 0, DRAW_PIXEL, DRAW, }; class generic_message_base : std::enable_shared_from_this { public: virtual ~generic_message_base() = default; 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("size {}", get_size()); std::cout << "MSG WAS SNT \n"; 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() = default; 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)); } virtual void handle_message(render_interface* renderer) override { renderer->update_rect(position, size, pixel_); } vec2 position; vec2 size; pixel pixel_; }; class draw_pixel : public generic_message { public: virtual ~draw_pixel() = default; 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 draw : public generic_message { public: virtual ~draw() = default; virtual uint32_t get_size() const override { return sizeof(*this); } virtual void handle_message() override {} virtual void handle_message(render_interface* renderer) override { renderer->draw(); } }; class Serializer {}; } // namespace protocol class cli_renderer : public render_interface { public: cli_renderer(size_t screen_size) : size_(screen_size), screen_{screen_size, std::vector{screen_size}} {} virtual ~cli_renderer() = default; virtual void update_pixel(protocol::vec2 position, protocol::pixel pixel) override { screen_[position.y][position.x] = pixel; } virtual void update_rect(protocol::vec2 position, protocol::vec2 width, protocol::pixel pixel) override { for (int y = position.y; y < size_ && y < width.y + position.y; ++y) { for (int x = position.x; x < size_ && x < width.x + position.x; ++x) update_pixel(protocol::vec2{x, y}, pixel); } } 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: size_t size_; std::vector> screen_; }; } // namespace commons