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");
}
}