I built a project in which I provide a string input or a whole matrix to configure a frame, create a bunch of different frames and push them into a queue and finally print them in order of the queue.
I would like some advice on how to improve the design of the frame class as I feel it became a spaghetti code. I'll be happy to also know what changes I can make for better performance and maybe variable name ideas because I feel like I didn't give my variables proper and understandable names.
hpp file:
#pragma once #include <vector> #include <string> #include <queue> #include <chrono> #include <unordered_map> #include <map> using frame_matrix = std::vector<std::vector<std::pair<char, std::string>>>; const std::unordered_map<std::string, std::string> colors = {{"red", "\033[31m"}, {"green", "\033[32m"}, {"blue", "\033[34m"}, {"yellow", "\033[33m"}, {"reset", "\033[0m"}}; class frame { private: std::string color; void initialize_frame(); public: frame_matrix current_frame; const static size_t AMOUNT_OF_INPUT_OPTIONS = 6; const static size_t FRAME_WIDTH = 30; const static size_t FRAME_HEIGHT = 20; const static char INPUT_DELIMITER = ','; const static char BACKGROUND = '#'; frame(); frame(const std::string& input); frame_matrix get_current_frame() const; void alter_frame(const std::string& input); void set_current_frame(const frame_matrix& new_current_frame); void print_frame(); bool parse_input(const std::string& input); bool is_valid_input(std::string height_start, std::string height_length, std::string range_start, std::string range_length, std::string printable_char,std::string color); }; class graphical_visualizer { private: std::queue<frame> frame_queue; public: graphical_visualizer(); std::queue<frame> get_frame_queue() const; void add_frame(frame frame); void print_sequence(const std::chrono::milliseconds millis); }; struct input { size_t height_start; size_t height_length; size_t width_start; size_t width_length; char symbol; std::string color; };
cpp file
#include "graphical_visualizer.hpp" #include <iostream> #include <sstream> #include <thread> frame::frame() { initialize_frame(); } frame::frame(const std::string& input) { initialize_frame(); alter_frame(input); } frame_matrix frame::get_current_frame() const { return current_frame; } void frame::alter_frame(const std::string& input) { parse_input(input); } void frame::set_current_frame(const frame_matrix& new_current_frame) { current_frame = new_current_frame; } void frame::print_frame() { for(const std::vector<std::pair<char, std::string>>& line : current_frame) { for(const std::pair<char, std::string>& current_char : line) { std::cout << current_char.second << current_char.first; std::cout << colors.at("reset"); } std::cout << std::endl; } } bool frame::parse_input(const std::string& input) { std::stringstream input_stream(input); std::string input_sections[AMOUNT_OF_INPUT_OPTIONS]; size_t input_sections_index = 0; while(std::getline(input_stream, input_sections[input_sections_index], INPUT_DELIMITER)) ++input_sections_index; if(!is_valid_input(input_sections[0], input_sections[1], input_sections[2], input_sections[3], input_sections[4], input_sections[5])) { return false; } int height_start = std::stoi(input_sections[0]); int height_length = std::stoi(input_sections[1]); int range_start = std::stoi(input_sections[2]); int range_length = std::stoi(input_sections[3]); std::string color = colors.at(input_sections[5]); char printable_char = input_sections[4][0]; //should always be a string of length 1 for(size_t i = height_start; i <= height_start + height_length - 1; ++i) { for(size_t j = range_start; j <= range_start + range_length - 1; ++j) { current_frame[i][j].first = printable_char; current_frame[i][j].second = color; } } return true; } void frame::initialize_frame() { for(size_t i = 0; i < FRAME_HEIGHT; ++i) { std::vector<std::pair<char, std::string>> line; for(size_t j = 0; j < FRAME_WIDTH; ++j) line.push_back({'#', colors.at("reset")}); current_frame.push_back(line); } } bool is_a_number(std::string number) { for(const char& ch : number) { if(!std::isdigit(ch)) return false; } return true; } bool frame::is_valid_input(std::string height_start, std::string height_length, std::string range_start, std::string range_length, std::string printable_char,std::string color) { std::unordered_map<std::string, std::string>::const_iterator pos = colors.find(color); if(pos == colors.end()) return false; if(!is_a_number(height_start) || !is_a_number(height_start) || !is_a_number(height_start) || !is_a_number(height_start)) { return false; } if(printable_char.size() != 1) return false; int height_start_int = std::stoi(height_start); int height_length_int = std::stoi(height_length); int range_start_int = std::stoi(range_start); int range_length_int = std::stoi(range_length); if(height_start_int < 0 || height_length_int + height_length_int - 1 >= FRAME_HEIGHT || range_start_int < 0 || range_start_int + range_length_int - 1 >= FRAME_WIDTH) return false; return true; } graphical_visualizer::graphical_visualizer() { frame_queue = {}; } std::queue<frame> graphical_visualizer::get_frame_queue() const { return frame_queue; } void graphical_visualizer::add_frame(frame frame) { frame_queue.push(frame); } void graphical_visualizer::print_sequence(const std::chrono::milliseconds millis) { std::queue<frame> local_temp_queue = frame_queue; while(!local_temp_queue.empty()) { local_temp_queue.front().print_frame(); local_temp_queue.pop(); std::this_thread::sleep_for(millis); system("clear"); } }