14#include "rapidjson/document.h"
15#include "rapidjson/writer.h"
16#include "rapidjson/stringbuffer.h"
17#include <SFML/Graphics.hpp>
53 #define SG_FILE "polynomials.json"
72 unsigned int y, x, h, w;
81 Window() noexcept :
c(true), a(false),
y(0), x(0), h(0), w(0),
o(newwin(0, 0, 0, 0)) {keypad(this->o, TRUE);
return;}
86 const char*
get_title() const noexcept {
return this->t.c_str();}
91 const unsigned int&
get_y() const noexcept {
return this->
y;}
96 const unsigned int&
get_x() const noexcept {
return this->x;}
101 const unsigned int&
get_height() const noexcept {
return this->h;}
106 const unsigned int&
get_width() const noexcept {
return this->w;}
116 void set_title(const ::std::string&& title)
noexcept {this->t = title; this->c =
true;
return;}
122 void set_coords(
const unsigned int y,
const unsigned int x)
noexcept {this->y =
y; this->x = x; this->c =
true;
return;}
128 void set_size(
const unsigned int h,
const unsigned int w)
noexcept {this->h = h; this->w = w; this->c =
true;
return;}
133 void set_active(
const bool active)
noexcept {
if (this-> a != active) {this->a = active; this->c =
true;}
return;}
138 virtual const unsigned int get_title_y() const noexcept {
return 0;}
143 virtual const unsigned int get_title_x() const noexcept {
return 0;}
148 const bool needs_update() noexcept {
if (this->c) {this->c =
false;
return true;}
return false;}
157 void place() {wclear(this->o); wrefresh(this->o); delwin(this->o); this->o = newwin(this->h, this->w, this->y, this->x); keypad(this->o, TRUE);
return;}
161 virtual ~Window() noexcept {delwin(this->o);
return;}
178 ::std::vector<::std::string> d;
193 const ::std::vector<::std::string>&
get_data() const noexcept {
return this->d;}
203 const unsigned int get_title_y() const noexcept
override {
return 1;}
208 const unsigned int get_title_x() const noexcept
override {
return (((this->w / 2) - (this->
t.size() / 2)) > 2) ? ((this->w / 2) - (this->
t.size() / 2)) : 3;}
213 void set_data(::std::vector<::std::string>&& data)
noexcept {this->d = data; this->
c =
true;
return;}
217 void scroll_up() noexcept {
if (this->s > 0) {this->s--;} this->
c =
true;
return;}
221 void scroll_down() noexcept {
if (this->s < (this->d.size() - this->h + (HPADD * 2) + 1)) {this->s++;} this->
c =
true;
return;}
243 const unsigned int get_title_y() const noexcept
override {
return 1;}
248 const unsigned int get_title_x() const noexcept
override {
return 4;}
268 Window *lwin, *rwin, *bwin;
276 signal(SIGWINCH, Terminal::resize);
286 unsigned int height, width;
287 getmaxyx(stdscr, height, width);
288 this->bwin->
set_size(PSIZE, width - (WPADD * 2));
289 this->lwin->
set_size(height - (HPADD * 3) - this->bwin->
get_height(), (width / 2) - (WPADD * 1.5));
295 bkgd(COLOR_PAIR(COLOR_ID)); refresh();
303 static void wflush(
Window*& win) {
307 wbkgd(win->
o, COLOR_PAIR(COLOR_ID));
309 wattron(win->
o, A_BOLD); waddnstr(win->
o, win->
get_title(), win->
get_width() - (WPADD * 2) - 2); wattroff(win->
o, A_BOLD);
311 for (
unsigned int i = owin->get_scroll_index(); i < ((owin->get_height() - 3 >= owin->get_data_size()) ? owin->get_data_size() : owin->get_height() - 3 - HPADD * 2) + owin->get_scroll_index(); i++) {
312 wmove(owin->o, i+2 - owin->get_scroll_index() + HPADD, 1 + TOFST); waddnstr(owin->o, owin->get_data()[i].c_str(), owin->get_width() - 2 - TOFST);
315 if (win->
is_active()) {wmove(win->
o, CPOSY, CPOSX); wattron(win->
o, A_BOLD | A_BLINK); waddch(win->
o,
'>'); wattroff(win->
o, A_BOLD | A_BLINK);}
323 static inline void resize(
int signal) {endwin(); refresh(); Terminal::instance->cbounds();
return;}
327 static inline void launch() {
328 initscr(); curs_set(2); start_color(); cbreak(); keypad(stdscr, TRUE); noecho();
329 init_pair(COLOR_ID, COLOR_YELLOW, COLOR_BLACK);
341 if (Terminal::instance !=
nullptr) {
delete Terminal::instance;}
342 return Terminal::instance =
new Terminal();
347 inline void flush() {Terminal::wflush(this->lwin); Terminal::wflush(this->rwin); Terminal::wflush(this->bwin); wmove(this->bwin->
o, this->bwin->get_title_y(), this->bwin->get_title_x() + this->bwin->get_title_size());
return;}
362 void set_prompt(const ::std::string prompt)
noexcept {this->bwin->
set_title(::std::move(prompt));
return;}
367 void set_ldata(::std::vector<::std::string> data)
noexcept {
dynamic_cast<OWindow *
>(this->lwin)->
set_data(::std::move(data));
return;}
372 void set_rdata(::std::vector<::std::string> data)
noexcept {
dynamic_cast<OWindow *
>(this->rwin)->
set_data(::std::move(data));
return;}
378 wmove(this->bwin->
o, this->bwin->get_title_y(), this->bwin->get_title_x() + this->bwin->get_title_size());
return wgetch(this->bwin->
o);
380 const int ch = getch();
381 if (ch == KEY_RESIZE) {resize_term(0, 0);}
384 return wgetch(this->bwin->
o);
391 const ::std::string
get_long_input()
const {
char* buffer =
new char(); echo(); wmove(this->bwin->
o, this->bwin->get_title_y(), this->bwin->get_title_x() + this->bwin->get_title_size()); wgetnstr(this->bwin->
o, buffer, this->bwin->get_width() - (this->bwin->get_title_x() + this->bwin->get_title_size()) - WPADD - 1); noecho(); return ::std::move(buffer);}
417 const ::std::string old_title = this->bwin->
get_title(); this->set_prompt(
"Result:"); this->flush();
418 wmove(this->bwin->
o, this->bwin->get_title_y(), this->bwin->get_title_x() + this->bwin->get_title_size());
419 waddnstr(bwin->
o, result.c_str(), this->bwin->get_width() - (this->bwin->get_title_x() + this->bwin->get_title_size()) - WPADD - 1);
420 wgetch(bwin->
o); this->set_prompt(old_title);
428 #define swp(l, r, b) this->lwin->set_active(l); this->rwin->set_active(r); this->bwin->set_active(b);
430 case LWIN: swp(
true,
false,
false);
break;
431 case RWIN: swp(
false,
true,
false);
break;
432 case BWIN: swp(
false,
false,
true);
break;
439 delete this->lwin;
delete this->rwin;
delete this->bwin;
440 Terminal::instance =
nullptr;
442 signal(SIGWINCH, SIG_DFL);
446 }; Terminal* Terminal::instance =
nullptr;
461 const int _xogn, _yogn;
465 unsigned int domain, image;
481 ::sf::VertexArray axes;
485 ::sf::RenderWindow window;
489 ::sf::RectangleShape line;
493 ::sf::CircleShape intersection;
497 ::sf::VertexArray representation;
502 this->window.clear(::sf::Color::Black);
503 this->window.draw(this->axes);
504 this->window.draw(this->line);
505 this->window.draw(this->representation);
506 this->window.draw(this->intersection);
507 this->window.draw(this->tooltip);
508 this->window.display();
return;
514 const int end = (this->xogn + this->domain);
515 this->axes[0].position = ::sf::Vector2f(0, -this->yogn);
516 this->axes[1].position = ::sf::Vector2f(this->domain, -this->yogn);
517 this->axes[2].position = ::sf::Vector2f(-this->xogn, 0);
518 this->axes[3].position = ::sf::Vector2f(-this->xogn, this->image);
519 for (
int x = this->xogn; x < end; x++) {
520 this->representation[(x - this->xogn)].position = ::sf::Vector2f((x - this->xogn), (-this->yogn - this->function.
get_value(x)));
521 this->representation[(x - this->xogn)].color = ::sf::Color::Red;
528 void resize(const ::sf::Event& event) {
529 this->domain = ::std::min(event.size.width, ::sf::VideoMode::getDesktopMode().width); this->image = ::std::min(event.size.height, ::sf::VideoMode::getDesktopMode().height);
530 this->window.setSize(::sf::Vector2u(this->domain, this->image)); this->representation = ::sf::VertexArray(::sf::LineStrip, this->domain); this->line.setSize(::sf::Vector2f(1, this->image));
531 this->window.setView(::sf::View(::sf::FloatRect(0, 0, this->domain, this->image)));
532 this->populate();
return;
539 static constexpr inline int inverse(
const int& n)
noexcept {
return ((n != 0) ? -n : n);}
547 Plane(
int ox,
int oy, const ::emth::Polynomial& func) : xogn(ox), yogn(oy), _xogn(ox), _yogn(oy), domain(::sf::VideoMode::getDesktopMode().width/2), image(::sf::VideoMode::getDesktopMode().height/2), function(func), window(::sf::VideoMode(::sf::VideoMode::getDesktopMode().width/2, ::sf::VideoMode::getDesktopMode().height/2),
"Polynomial: " + func.get_expression(), ::sf::Style::Titlebar | ::sf::Style::Close, ::sf::ContextSettings(0, 0, 16, 1, 1, 0, false)), axes(::sf::Lines, 4), representation(::sf::LineStrip, ::sf::VideoMode::getDesktopMode().width/2), line(::sf::Vector2f(1, ::sf::VideoMode::getDesktopMode().height/2)), intersection(5/2) {
548 this->window.setVerticalSyncEnabled(
true);
550 tooltip.setFont(this->font); this->tooltip.setCharacterSize(16); this->tooltip.setFillColor(::sf::Color::White);
551 this->axes[0].color = this->axes[1].color = this->axes[2].color = this->axes[3].color = ::sf::Color::White;
552 this->line.setFillColor(::sf::Color::Yellow); this->intersection.setFillColor(::sf::Color::Blue); this->intersection.setPointCount(25);
559 while(this->window.isOpen()) {
560 ::sf::Event event; ::std::stringstream ts;
561 while (window.pollEvent(event)) {
563 case ::sf::Event::Closed: this->window.close();
break;
564 case ::sf::Event::MouseMoved:
565 this->line.setPosition(event.mouseMove.x, 0);
566 this->intersection.setPosition(event.mouseMove.x - this->intersection.getRadius(), this->representation[event.mouseMove.x].position.y - this->intersection.getRadius());
567 ts = ::std::stringstream(); ts <<
"(" <<
event.mouseMove.x + this->xogn <<
"," << inverse(this->representation[event.mouseMove.x].position.y + this->yogn) <<
")"; tooltip.setString(ts.str());
568 tooltip.setPosition(event.mouseMove.x + 10, this->representation[event.mouseMove.x].position.y);
570 case ::sf::Event::KeyPressed:
571 switch(event.key.code) {
572 case ::sf::Keyboard::Up: this->yogn -= this->window.getSize().y/100;
break;
573 case ::sf::Keyboard::Down: this->yogn += this->window.getSize().y/100;
break;
574 case ::sf::Keyboard::Right: this->xogn += this->window.getSize().x/100;
break;
575 case ::sf::Keyboard::Left: this->xogn -= this->window.getSize().x/100;
break;
576 case ::sf::Keyboard::Space: this->xogn = this->_xogn; this->yogn = this->_yogn;
break;
577 } this->populate();
break;
578 case ::sf::Event::Resized: this->resize(event);
break;
594 const ::std::string filename;
600 Storage(const ::std::string file) noexcept : filename(::std::move(file)) {
return;}
605 const ::std::string
read() const noexcept {
607 ::std::ifstream file(this->filename);
608 if (!file.is_open()) {throw ::std::runtime_error(
"Input file does not exist");}
609 ::std::string contents((::std::istreambuf_iterator<char>(file)), ::std::istreambuf_iterator<char>());
610 file.close();
return contents;
611 }
catch(const ::std::exception& e) {
return "";}
618 const int write(const ::std::string contents)
const noexcept {
620 ::std::ofstream file(this->filename, ::std::ios::out | ::std::ios::trunc);
621 file << contents; file.close();
return 0;
622 }
catch (const ::std::exception& e) {
return 1;}
630 ::std::ifstream file(this->filename);
631 if (!file.is_open()) {
return false;}
632 file.close();
return true;
633 }
catch(const ::std::exception& e) {
return false;}
682 union {
char c;
int n;} value;
694 const ::std::string _input;
698 short unsigned int _pos;
704 static const ::std::string clean(
const std::string& input)
noexcept {
705 short unsigned int pos = 0; ::std::string result;
706 while (pos < input.size()) {
707 switch (input[pos]) {
708 case '+': result +=
'+';
break;
709 case '-': result +=
'-';
break;
710 case '*': result +=
'*';
break;
711 case '/': result +=
'/';
break;
712 default:
if (Lexer::is_integer(input[pos])) {result += input[pos];}
break;
722 static constexpr inline bool is_integer(
const char& c)
noexcept {
return (c >=
'0' && c <=
'9');}
728 Lexer(
const std::string& input) noexcept : _input(Lexer::clean(input)), _pos(0) {}
734 if (this->_pos >= this->_input.size()) {
return {TokenType::T_EOF, {0}};}
735 switch (this->_input[this->_pos]) {
736 case '+': this->_pos++;
return {TokenType::T_PLUS, {0}};
737 case '-': this->_pos++;
return {TokenType::T_MINUS, {0}};
738 case '*': this->_pos++;
return {TokenType::T_MULTIPLICATION, {0}};
739 case '/': this->_pos++;
return {TokenType::T_DIVISION, {0}};
740 default: this->_pos++;
return {TokenType::T_NUMBER, {(char) this->_input[this->_pos - 1]}};
764 Parser(
const std::string& input) noexcept : _lexer(input) {}
770 bool positive =
true;
771 ::std::string buffer =
"0";
774 switch (token.
type) {
775 case TokenType::T_MINUS: positive = !positive;
break;
776 case TokenType::T_NUMBER: buffer += token.
value.c;
break;
777 case TokenType::T_EOF:
return positive ? std::stoi(buffer) : -1 * std::stoi(buffer);
788 std::vector<emth::Polynomial> data; std::vector<TokenType> operations;
791 if (token.
type == TokenType::T_EOF) {
break;}
792 switch (token.
type) {
793 case TokenType::T_NUMBER:
if (!hook && (
unsigned int) std::stoi(std::string(1, token.
value.c)) < ps.size()) {data.push_back(ps[std::stoi(std::string(1, token.
value.c))]); hook =
true;}
break;
794 default:
if (hook) {operations.push_back(token.
type); hook =
false;}
break;
797 for (
unsigned int i = 0; i < operations.size(); i++) {
798 if (operations[i] == TokenType::T_MULTIPLICATION || operations[i] == TokenType::T_DIVISION) {
799 switch (operations[i]) {
800 case TokenType::T_MULTIPLICATION: data[i] *= data[i + 1];
break;
801 case TokenType::T_DIVISION: data[i] /= data[i + 1];
break;
802 } data.erase(data.begin() + i + 1); operations.erase(operations.begin() + i); i--;
805 for (
unsigned int i = 0; i < operations.size(); i++) {
806 switch (operations[i]) {
807 case TokenType::T_PLUS: data[i] += data[i + 1];
break;
808 case TokenType::T_MINUS: data[i] -= data[i + 1];
break;
809 } data.erase(data.begin() + i + 1); operations.erase(operations.begin() + i); i--;
824 #define V_MENU {::std::string("[ESC] Exit program"), ::std::string("[TAB] Cycle focus"), ::std::string("[E] Add polynomial"), ::std::string("[Q] Remove polynomial"), ::std::string("[SPACE] New operation")}
825 #define V_OPERATION {::std::string("[ESC] Back"), ::std::string("[TAB] Cycle focus"), ::std::string("[1] Evaluate operation"), ::std::string("[2] Derivative operation"), ::std::string("[3] Integral operation"), ::std::string("[4] Root finding operation"), ::std::string("[5] Drawing operation"), ::std::string("[SPACE] Arithmetic operations")}
826 #define V_SCROLL {::std::string("[ESC] Exit program"), ::std::string("[UP ARROW] Scroll up"), ::std::string("[DOWN ARROW] Scroll down")}
842 rapidjson::Document json;
846 ::std::vector<emth::Polynomial> polynomials;
854 Application() noexcept : terminal(Terminal::init()), storage(
Storage(SG_FILE)), active(BWIN) {
855 if (!this->storage.
exists()) {this->json.SetArray();}
else {this->json.Parse(this->storage.
read().c_str()); this->read_json();}
859 this->terminal->
set_rdata(this->stringify_polynomials());
866 const int save_json()
const noexcept {
868 rapidjson::StringBuffer buffer;
869 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
870 this->json.Accept(writer);
871 this->storage.
write(buffer.GetString());
872 }
catch (::std::exception& e) {
return 1;}
return 0;
878 const int read_json()
noexcept {
880 if (this->json.IsArray()) {
881 for (
const auto& o : this->json.GetArray()) {
885 }
catch (::std::exception& e) {
return 1;}
return 0;
891 const int cycle_focus()
noexcept {
892 #define swpa(o) this->active = o; this->terminal->swap_active(o);
893 switch(this->active) {
894 case LWIN: swpa(RWIN);
return 1;
895 case RWIN: swpa(BWIN);
break;
896 case BWIN: swpa(LWIN);
return 1;
903 const int scroll_loop()
noexcept {
905 this->terminal->
flush();
908 case KEY_ESC:
return 0;
909 case KEY_TAB:
return 1;
910 case KEY_UP: this->terminal->
scroll_up(this->active);
break;
911 case KEY_DOWN: this->terminal->
scroll_up(this->active);
break;
912 } this->terminal->
flush();
919 const int get_polynomial()
noexcept {
923 this->add_polynomial(polynomial);
924 }
catch (::std::exception& e) {
return 1;}
925 this->terminal->
set_prompt(
"Option:");
return 0;
933 this->json.PushBack(rapidjson::Value(polynomial.
get_expression().c_str(), this->json.GetAllocator()).Move(), this->json.GetAllocator());
934 this->polynomials.push_back(::std::move(polynomial));
935 this->terminal->
set_rdata(this->stringify_polynomials());
937 }
catch (::std::exception& e) {
return 1;}
944 const int remove_polynomial(
const unsigned int id)
noexcept {
946 if (id < this->polynomials.size()) {
947 this->polynomials.erase(this->polynomials.begin() +
id);
948 this->json.Erase(this->json.Begin() +
id);
949 this->terminal->
set_rdata(this->stringify_polynomials());
951 }
else {this->terminal->
echo_result(
"No polynomial with index:" + std::to_string(
id));}
952 }
catch (::std::exception& e) {
return 1;}
return 0;
958 const ::std::vector<::std::string> stringify_polynomials()
const noexcept {::std::vector<::std::string> buffer;
for (
unsigned int i = 0; i < this->polynomials.size(); i++) {buffer.push_back(
"[" + std::to_string(i) +
"] " + ::std::move(this->polynomials[i].get_expression()));}
return buffer;}
963 const int main_loop() {
965 this->terminal->
flush();
968 case KEY_ESC:
return 0;
case KEY_SPC:
return 1;
969 case KEY_TAB:
return 2;
970 case KEY_E: this->get_polynomial();
break;
971 case KEY_Q: this->terminal->
set_prompt(
"Id:"); this->terminal->
flush(); this->remove_polynomial(Application::to_int(this->terminal->
get_long_input())); this->terminal->
set_prompt(
"Option:");
break;
972 } this->terminal->
flush();
979 const int operation_loop() {
980 if (!this->polynomials.empty()) {
982 this->terminal->
flush();
985 case KEY_ESC:
return 0;
case KEY_TAB:
return 2;
986 case KEY_SPC: this->calculate(0);
return 1;
987 case KEY_1: this->calculate(1);
return 1;
988 case KEY_2: this->calculate(2);
return 1;
989 case KEY_3: this->calculate(3);
return 1;
990 case KEY_4: this->calculate(4);
return 1;
991 case KEY_5: this->calculate(5);
return 1;
992 } this->terminal->
flush();
994 } this->terminal->
echo_result(
"No polynomials registered!");
return 0;
1000 void calculate(
const int t)
noexcept {
1007 if (in[0] ==
'_') {this->add_polynomial(r);}
1008 }
catch (
int e) {this->terminal->
echo_result(
"No polynomial with index:" + std::to_string(e));}
1010 const unsigned int sinput = Application::to_int(this->terminal->
get_long_input());
1011 if (sinput < this->polynomials.size()) {
1015 this->terminal->
echo_result((::std::stringstream() << this->polynomials[sinput].get_value(Application::to_int(this->terminal->
get_long_input()))).str());
1017 case 2: this->terminal->
echo_result(this->polynomials[sinput].get_derivative().get_expression());
break;
1018 case 3: this->terminal->
echo_result(this->polynomials[sinput].get_integral().get_expression());
break;
1019 case 4: this->terminal->
echo_result(vtoss(this->polynomials[sinput].get_roots()));
break;
1020 case 5: launch_plane(this->polynomials[sinput]);
break;
1022 }
else {this->terminal->
echo_result(
"No polynomial with index:" + std::to_string(sinput));}
1023 } this->terminal->
set_prompt(
"Option:");
return;
1034 std::thread plane_thread([function, x, y](){
Plane p(-x, -y, function); p.
run();
return;});
1035 plane_thread.detach();
return;
1042 static const int to_int(const ::std::string& number)
noexcept {
return Parser(number).
parse_number();}
1048 static const std::string vtoss(
const std::vector<std::complex<double>>& v)
noexcept {std::stringstream ss; ss <<
"["; ctoss(ss, v[0]);
for(
unsigned int i = 1; i < v.size(); i++) {ss <<
", "; ctoss(ss, v[i]);} ss <<
"]";
return ss.str();}
1054 static const void ctoss(std::stringstream& ss,
const std::complex<double>& c)
noexcept {ss <<
"(";
if (std::abs(c.real()) > 1e-9 && std::abs(c.imag()) > 1e-9) {ss << c.real() <<
" " << ((c.imag() > 0) ?
"+ " :
"- ") << std::abs(c.imag()) <<
"i";}
else if (std::abs(c.real()) > 1e-9) {ss << c.real();}
else if (std::abs(c.imag()) > 1e-9) {ss << c.imag() <<
"i";}
else {ss <<
"0";} ss <<
")";
return;}
1061 if (Application::instance !=
nullptr) {
delete Application::instance;}
1070 switch(this->main_loop()) {
1072 case 1:
if (this->operation_loop() == 2 && this->cycle_focus() == 1) {hook =
true;}
break;
1073 case 2:
if (this->cycle_focus() == 1) {hook =
true;}
break;
1076 switch (this->scroll_loop()) {
1078 case 1:
if (this->cycle_focus() != 1) {hook =
false;};
break;
1087 Application::instance =
nullptr;
1088 delete this->terminal;
1089 this->save_json();
return;
1091 }; Application* Application::instance =
nullptr;
Class that contains the application inner logic.
void run()
Main loop fallback, basically it starts the application event loop.
static Application * init() noexcept
Static function for building the singleton static instance.
~Application() noexcept
Default destructor, it deletes the Terminal pointer, sets the singleton instance to nullptr,...
Window class extension for input.
~IWindow() noexcept=default
Default destructor.
const unsigned int get_title_y() const noexcept override
Gets the title y coordinate.
const unsigned int get_title_x() const noexcept override
Gets the title x coordinate.
IWindow() noexcept
Default constructor.
Class that works as a token supplier for the Parser class.
const Token next() noexcept
Function that returns the next Token in the input provided in the constructor.
~Lexer() noexcept=default
Default destructor.
Lexer(const std::string &input) noexcept
Standalone constructor for the Lexer class.
Window class extension for output.
OWindow() noexcept
Default constructor.
const unsigned int get_data_size() const noexcept
Gets the data vector size.
void scroll_down() noexcept
Scrolls down, internally adds to the scroll index within certain bounds.
const ::std::vector<::std::string > & get_data() const noexcept
Gets the data vector.
const unsigned int & get_scroll_index() const noexcept
Gets if the scroll index.
const unsigned int get_title_y() const noexcept override
Gets the title y coordinate.
~OWindow() noexcept=default
Default destructor.
const unsigned int get_title_x() const noexcept override
Gets the title x coordinate.
void scroll_up() noexcept
Scrolls up, internally substracts from the scroll index within certain bounds.
void set_data(::std::vector<::std::string > &&data) noexcept
Sets the data vector.
Class that wraps a std::string and parses it as a number or as a operation.
~Parser() noexcept=default
Default destructor.
const emth::Polynomial parse_operation(const ::std::vector< emth::Polynomial > &ps)
Function for parsing std::string as a mathematical operation consisting of Polynomials represented as...
const int parse_number() noexcept
Function for parsing a plus, minus and number Tokens as a positive or negative int.
Parser(const std::string &input) noexcept
Standalone constructor for the Parser class.
Plane class to draw a function in the Cartesian plane.
Plane(int ox, int oy, const ::emth::Polynomial &func)
The main constructor.
void run()
Runs the main application loop, processing events.
Storage class to read and write to a file.
~Storage() noexcept=default
Default destructor.
const ::std::string read() const noexcept
The read function that returns the whole file as a std:.string.
Storage(const ::std::string file) noexcept
The main constructor.
bool exists() const noexcept
This function check if the filename exists.
const int write(const ::std::string contents) const noexcept
The write function that overwrites the whole file with a std::string.
Terminal class to manage the terminal through curses.
void scroll_up(const unsigned int id) noexcept
Function for scrolling up the left or right window depending on the provided id.
const ::std::string get_long_input() const
Function for getting long single string input from the Terminal.
~Terminal() noexcept
Default destructor, it deletes the Window pointers, sets the singleton instance to nullptr,...
void flush()
Function for flushin all the Terminal's Windows.
void set_ltitle(const ::std::string title) noexcept
Function for setting the title of the left Window.
const int get_short_input() const
Function for getting short single char input from the Terminal.
static Terminal * init() noexcept
Static function for building the singleton static instance.
void set_ldata(::std::vector<::std::string > data) noexcept
Function for setting data vector of the left Window.
void scroll_down(const unsigned int id) noexcept
Function for scrolling down the left or right window depending on the provided id.
void echo_result(const ::std::string &result)
Echoes the provided result to the prompt and waits for a key press.
void set_rdata(::std::vector<::std::string > data) noexcept
Function for setting data vector of the right Window.
void set_rtitle(const ::std::string title) noexcept
Function for setting the title of the right Window.
void swap_active(const unsigned int id) noexcept
Swaps the active window to the one matching the provide id.
void set_prompt(const ::std::string prompt) noexcept
Function for setting the prompt of the bottom Window.
Generic class for wrapping a curses WINDOW.
const unsigned int & get_height() const noexcept
Returns the height value.
void set_active(const bool active) noexcept
Sets the active boolean to the provided value.
const unsigned int & get_x() const noexcept
Returns the x coordinate.
virtual const unsigned int get_title_x() const noexcept
Gets the title x coordinate.
const bool needs_update() noexcept
Gets if the window needs a redraw.
void place()
Deletes the WINDOW pointer and creates a new WINDOW at the class coordinates.
const unsigned int & get_y() const noexcept
Returns the y coordinate.
unsigned int y
Four unsigned ints: x and y for the coordinates relative to the console window, w and h for the size ...
const unsigned int & get_width() const noexcept
Returns the width value.
const bool is_active() const noexcept
Gets if the window is active/focused.
::std::string t
String t: window title.
virtual const unsigned int get_title_y() const noexcept
Gets the title y coordinate.
const char * get_title() const noexcept
Returns the c_str() const char pointer of the title std::string.
const unsigned int get_title_size() const noexcept
Returns the title size.
WINDOW * o
Pointer to the curses WINDOW object.
virtual ~Window() noexcept
Calls curses delwin() function on the curses WINDOW object and returns.
void set_size(const unsigned int h, const unsigned int w) noexcept
Sets the size.
void set_coords(const unsigned int y, const unsigned int x) noexcept
Sets the y and x coordinates.
bool c
Two booleans: c for knowing if contents changed, and a for knowing if window is active.
Window() noexcept
Generic constructor with default values.
void set_title(const ::std::string &&title) noexcept
Sets the title.
Class for representing and operating polynomials.
double get_value(const double &x) const noexcept
Calculus function for getting the value of the Polynomial at a point.
bool is_empty() const noexcept
Function for knowing if the polynomial has or not any monomials.
std::string get_expression() const noexcept
Getter function for getting the expression of the Polynomial.
Class that wraps a std::string and parses it as a Monomial or as a Polynomial.
emth::Polynomial parse_polynomial() noexcept
Function that parses the input as a Polynomial.
This is the main header file for the emath library.
This is the main header file for the equation parser.
This file contains some fonts as a unsigned char arrays.
unsigned char ROBOTO_BOLD[]
The Roboto Bold font as a unsigned char array.
int main()
The main function that creates the efc::Application instance, runs it and when it finishes it deletes...
Englobes all the classes and functions of the emath text user interface.
TokenType
Enum with all the possible Token types.
@ T_DIVISION
Division sign type.
@ T_MULTIPLICATION
Multiplication sign type.
Struct for representing a token as a type and a value.
const TokenType type
The token's type as a TokenType.
union efc::Token::@0 value
A union representing the value of the Token as a char or as a int.