#include "Calculator.h" #include "modules/ImguiModule/ImguiModule.h" #include #include Calculator::Calculator(Archimedes::App* a, void* h) : Archimedes::Module(a, h) { name = "Calculator"; ImguiModule* im = new ImguiModule(a, h); deps[*im] = im; } Calculator::~Calculator() { if(app) { ImguiModule* im; { im = (ImguiModule*) moduleInstances[ImguiModule()]; } im->releaseContext(ImGui::GetCurrentContext()); } } void Calculator::onLoad() { ImguiModule* im; { im = (ImguiModule*) moduleInstances[ImguiModule()]; } if(!im) { std::cout << "No ImguiModule for Calculator!\n"; std::abort(); } ImGui::SetCurrentContext(im->aquireContext()); } void Calculator::run() { if(open) { basicCalculator(); } else { app->emitEvent(new Archimedes::DoUnloadModuleEvent(name)); } } void Calculator::index(std::string equation, std::unordered_map& nodes) { unsigned int idx = 0; nodes.clear(); const static std::string operators[] = { "(", ")", "^", "*", "/", "+", "-" }; for(const std::string& s : operators) { while(equation.find(s, idx) != std::string::npos) { int next = equation.find(s, idx); nodes[next] = equation.substr(next, s.length()); idx = next + s.length(); } idx = 0; } // -3+8*6-(8+4)^9/5 for(unsigned int i = 0; i < equation.length(); i++) { static unsigned int begin = 0, end = 0; if(nodes.find(i) == nodes.end()) { if(nodes.find(i - 1) != nodes.end() || i == 0) { //first digit of expression begin = i; } if(nodes.find(i + 1) != nodes.end() || i == equation.length() - 1) { //character after last digit of expression end = i + 1; nodes[begin] = equation.substr(begin, end - begin); nodes[end - 1] = equation.substr(begin, end - begin); } } } } double Calculator::evaluate(std::string equation, std::unordered_map& evalStr) { char op = '^'; while(equation.find(op) == std::string::npos) { switch(op) { case '^': op = '*'; break; case '*': op = '/'; break; case '/': op = '+'; break; case '+': op = '-'; break; case '-': //no operator if(evalStr.find(equation.front()) != evalStr.end()) { return evaluate(evalStr[equation.front()], evalStr); } else { return std::stod(equation); } break; } } //op is now the appropriate operator //if either term is a placeholder, evaluate and substitute. double a, b; if(evalStr.find(equation.front()) != evalStr.end()) { a = evaluate(evalStr[equation.front()], evalStr); } else { if(equation.find(op) == 0 && op == '-') { a = 0; } else { a = std::stod(equation.substr(0, equation.find(op))); } } if(evalStr.find(equation.back()) != evalStr.end()) { b = evaluate(evalStr[equation.back()], evalStr); } else { b = std::stod(equation.substr(equation.find(op) + 1)); } switch(op) { case '^': return pow(a, b); case '*': return a * b; case '/': return a / b; case '+': return a + b; case '-': return a - b; } } std::string Calculator::calculate(std::string equation) { //PEMDAS while(equation.find(' ') != std::string::npos) { equation.erase(equation.find(' '), 1); } std::unordered_map nodes; std::unordered_map evalStr; std::string eval = "a"; unsigned int idx = 0; index(equation, nodes); idx = 0; // () while(equation.find(')', idx) != std::string::npos) { int end = equation.find(')'); int begin = equation.rfind('(', end); evalStr[eval.front()] = calculate(equation.substr(begin + 1, (end - begin) - 1)); equation.replace(begin, (end - begin) + 1, eval); eval.front()++; idx = end + 1; } idx = 0; index(equation, nodes); // ^ while(equation.find('^', idx) != std::string::npos) { int mid = equation.find('^'); int begin = equation.find(nodes[mid - 1] + nodes[mid]); int end = equation.find(nodes[mid] + nodes[mid + 1], begin) + (nodes[mid] + nodes[mid + 1]).length(); evalStr[eval.front()] = equation.substr(begin, end - begin); equation.replace(begin, end - begin, eval); eval.front()++; idx = end + 1; } idx = 0; index(equation, nodes); // * or / while(equation.find('*', idx) != std::string::npos || equation.find('/', idx) != std::string::npos) { if(equation.find('*', idx) < equation.find('/', idx) && equation.find('*', idx) != std::string::npos) { int mid = equation.find('*'); int begin = equation.find(nodes[mid - 1] + nodes[mid]); int end = equation.find(nodes[mid] + nodes[mid + 1], begin) + (nodes[mid] + nodes[mid + 1]).length(); evalStr[eval.front()] = equation.substr(begin, end - begin); equation.replace(begin, end - begin, eval); eval.front()++; idx = end + 1; } else if(equation.find('/', idx) != std::string::npos) { int mid = equation.find('/'); int begin = equation.find(nodes[mid - 1] + nodes[mid]); int end = equation.find(nodes[mid] + nodes[mid + 1], begin) + (nodes[mid] + nodes[mid + 1]).length(); evalStr[eval.front()] = equation.substr(begin, end - begin); equation.replace(begin, end - begin, eval); eval.front()++; idx = end + 1; } } idx = 0; index(equation, nodes); // + or - while(equation.find('+', idx) != std::string::npos || equation.find('-', idx) != std::string::npos) { if(equation.find('+', idx) < equation.find('-', idx) && equation.find('+', idx) != std::string::npos) { int mid = equation.find('+'); int begin = equation.find(nodes[mid - 1] + nodes[mid]); int end = equation.find(nodes[mid] + nodes[mid + 1], begin) + (nodes[mid] + nodes[mid + 1]).length(); evalStr[eval.front()] = equation.substr(begin, end - begin); equation.replace(begin, end - begin, eval); eval.front()++; idx = end + 1; } else if(equation.find('-', idx) != std::string::npos) { int mid = equation.find('-'); int begin = mid; if(nodes.find(mid - 1) != nodes.end()) { begin = equation.find(nodes[mid - 1] + nodes[mid]); } int end = equation.find(nodes[mid] + nodes[mid + 1], begin) + (nodes[mid] + nodes[mid + 1]).length(); evalStr[eval.front()] = equation.substr(begin, end - begin); equation.replace(begin, end - begin, eval); eval.front()++; idx = end + 1; } } return std::to_string(evaluate(equation, evalStr)); } void Calculator::basicCalculator() { static bool b = true; static std::string s; if(b) { ImGui::Begin("Basic Calculator", &open); ImGui::Text("%s", s.c_str()); ImGui::BeginGroup(); { if(ImGui::Button("AC")) { s.clear(); } ImGui::SameLine(); if(ImGui::Button("()")) { if(parenthesis) { s += " ( "; } else { s += " ) "; } parenthesis = !parenthesis; } ImGui::SameLine(); if(ImGui::Button("Gr")) { graphing = true; } ImGui::SameLine(); if(ImGui::Button("=")) { s = calculate(s); } } ImGui::EndGroup(); ImGui::BeginGroup(); { for(int i = 1; i < 4; i++) { ImGui::BeginGroup(); for(int j = 6; j >= 0; j -= 3) { if(ImGui::Button(std::to_string(i + j).c_str())) { s += std::to_string(i + j); } } ImGui::EndGroup(); if(i < 3) { ImGui::SameLine(); } } if(ImGui::Button("0")) { s += "0"; } ImGui::SameLine(); if(ImGui::Button(".")) { s += "."; } ImGui::SameLine(); if(ImGui::Button("del")) { if(!s.empty()) { if(s.back() == ' ') { s.pop_back(); if(s.back() == '(' || s.back() == ')') { parenthesis = !parenthesis; } s.pop_back(); s.pop_back(); } else { s.pop_back(); } } } } ImGui::EndGroup(); ImGui::SameLine(); ImGui::BeginGroup(); if(ImGui::Button("+")) { s += " + "; } if(ImGui::Button("-")) { s += " - "; } if(ImGui::Button("*")) { s += " * "; } if(ImGui::Button("/")) { s += " / "; } ImGui::EndGroup(); ImGui::End(); } } void Calculator::graphingCalculator() { }