Version 2 Release!

- Added GUI
- Added Evaluation
- Added Recursive brackets support
- Added Two way evaluation
- Added ExprTreeReveresed
- Fixed bracket matching
- Fixed Log
- Fixed Error Reporting
This commit is contained in:
Ayham Mamoun 2019-03-23 13:46:21 +03:00
parent 818d12fcf2
commit b76971ad82
77 changed files with 1373 additions and 189 deletions

3
.gitignore vendored
View File

@ -2,4 +2,5 @@
bin-int/
bin/
x64/
x64/
release/

BIN
Debug/QuicMafGui.exe Normal file

Binary file not shown.

BIN
Debug/QuicMafGui.ilk Normal file

Binary file not shown.

BIN
Debug/QuicMafGui.pdb Normal file

Binary file not shown.

View File

@ -5,6 +5,8 @@ VisualStudioVersion = 15.0.28307.329
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QuicMaf", "QuicMaf\QuicMaf.vcxproj", "{EA73D661-B6EB-4156-AC92-A470A6683307}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QuicMafGui", "QuicMafGui\QuicMafGui.vcxproj", "{7CDC5570-9785-446C-8CB9-C03E6D98927F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -21,6 +23,14 @@ Global
{EA73D661-B6EB-4156-AC92-A470A6683307}.Release|x64.Build.0 = Release|x64
{EA73D661-B6EB-4156-AC92-A470A6683307}.Release|x86.ActiveCfg = Release|Win32
{EA73D661-B6EB-4156-AC92-A470A6683307}.Release|x86.Build.0 = Release|Win32
{7CDC5570-9785-446C-8CB9-C03E6D98927F}.Debug|x64.ActiveCfg = Debug|x64
{7CDC5570-9785-446C-8CB9-C03E6D98927F}.Debug|x64.Build.0 = Debug|x64
{7CDC5570-9785-446C-8CB9-C03E6D98927F}.Debug|x86.ActiveCfg = Debug|Win32
{7CDC5570-9785-446C-8CB9-C03E6D98927F}.Debug|x86.Build.0 = Debug|Win32
{7CDC5570-9785-446C-8CB9-C03E6D98927F}.Release|x64.ActiveCfg = Release|x64
{7CDC5570-9785-446C-8CB9-C03E6D98927F}.Release|x64.Build.0 = Release|x64
{7CDC5570-9785-446C-8CB9-C03E6D98927F}.Release|x86.ActiveCfg = Release|Win32
{7CDC5570-9785-446C-8CB9-C03E6D98927F}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

28
QuicMaf/Log.h Normal file
View File

@ -0,0 +1,28 @@
/*
* File: Log.h
* Author: Alberto Lepe <dev@alepe.com>
* Edited By: Ayham Mamoun <ayhamaboualfadl@gmail.com>
*
* Created on December 1, 2015, 6:00 PM
*/
#ifndef LOG_H
#define LOG_H
#include <vector>
#include <string>
#include <sstream>
using namespace std;
class LOG {
public:
vector<string>* qm_log = new vector<string>();
LOG() {}
LOG &operator<<(const string &msg) {
qm_log->push_back(msg);
return *this;
}
private:
};
#endif /* LOG_H */

View File

@ -26,26 +26,26 @@
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
@ -70,8 +70,24 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)bin\$(Configuration)-$(Platform)\</OutDir>
<IntDir>$(SolutionDir)bin-int\$(Configuration)-$(Platform)\</IntDir>
<OutDir>$(SolutionDir)bin/$(Configuration)-$(Platform)/</OutDir>
<IntDir>$(SolutionDir)bin-int/$(Configuration)-$(Platform)/</IntDir>
<IncludePath>$(SolutionDir)\QuicMaf\vendor\spdlog\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)bin/$(Configuration)-$(Platform)/</OutDir>
<IntDir>$(SolutionDir)bin-int/$(Configuration)-$(Platform)/</IntDir>
<IncludePath>$(SolutionDir)\QuicMaf\vendor\spdlog\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)bin/$(Configuration)-$(Platform)/</OutDir>
<IntDir>$(SolutionDir)bin-int/$(Configuration)-$(Platform)/</IntDir>
<IncludePath>$(SolutionDir)\QuicMaf\vendor\spdlog\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)bin/$(Configuration)-$(Platform)/</OutDir>
<IntDir>$(SolutionDir)bin-int/$(Configuration)-$(Platform)/</IntDir>
<IncludePath>$(SolutionDir)\QuicMaf\vendor\spdlog\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@ -79,6 +95,7 @@
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\QuicMaf\vendor\spdlog\include;$(IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -87,6 +104,7 @@
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\QuicMaf\vendor\spdlog\include;$(IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -97,6 +115,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\QuicMaf\vendor\spdlog\include;$(IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@ -111,6 +130,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\QuicMaf\vendor\spdlog\include;$(IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@ -126,6 +146,7 @@
<ClCompile Include="maths\solver\term_rewriter\ds\TermPool.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Log.h" />
<ClInclude Include="maths\solver\term_rewriter\ds\ExprTree.h" />
<ClInclude Include="maths\defines.h" />
<ClInclude Include="maths\Equations.h" />
@ -144,6 +165,7 @@
<ClInclude Include="maths\solver\Solver.h" />
<ClInclude Include="maths\solver\term_rewriter\QMEvaluator.h" />
<ClInclude Include="maths\solver\term_rewriter\ds\TermPool.h" />
<ClInclude Include="qm.h" />
<ClInclude Include="vendor\lexertk.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -92,5 +92,11 @@
<ClInclude Include="maths\solver\term_rewriter\QMEvalHelper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="qm.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Log.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -13,9 +13,10 @@
#include "maths/solver/term_rewriter/ds/ExprTree.h"
#define MAIN_APP
//#define APP_TEST
#include "Log.h"
//#define MAIN_APP
//#define APP_TEST
#ifdef MAIN_APP
@ -31,6 +32,7 @@ int main() {
cout << "Solution: " << endl;
Solver solver;
solver.CheckEqu(input);
solver.Parse(input);
solver.Solve();
@ -54,24 +56,6 @@ int main() {
#ifdef APP_TEST
int main() {
lexertk::generator lexer;
lexer.process("12341-(2x+3)");
auto result = tokenize(lexer);
Solver solver;
solver.Parse("4+3=4x+6");
solver.Solve();
for (auto *lwing : solver.mEquation->lwing)
cout << lwing->to_str();
cout << "=";
for (auto *rwing : solver.mEquation->rwing)
cout << rwing->to_str();
cout << endl;
system("PAUSE");
return 0;
}

View File

@ -17,8 +17,12 @@ struct Equation {
vector<Term*> lwing;
vector<Term*> rwing;
LOG* log = nullptr;
// TODO: Optimize this mess
void Parse(lexertk::generator expression) {
tok_log = log;
string lwing_str;
string rwing_str;
@ -38,10 +42,18 @@ struct Equation {
lexertk::generator lwing_lexer;
lwing_lexer.process(lwing_str);
lwing = tokenize(lwing_lexer);
if (lwing.empty()) {
return; // error occured
}
lexertk::generator rwing_lexer;
rwing_lexer.process(rwing_str);
rwing = tokenize(rwing_lexer);
if (lwing.empty()) {
return; // error occured
}
tok_log = nullptr;
}
};

View File

@ -1,5 +1,6 @@
#ifndef DEFINES_H
#define DEFINES_H
#include "../Log.h"
#include <vector>
#include <deque>
@ -17,6 +18,7 @@
#include <functional>
using namespace std;
#define DEF_C -999

View File

@ -4,10 +4,48 @@ void Solver::Parse(string equation) {
mEquation = new Equation();
lexertk::generator lexer;
lexer.process(equation);
mEquation->log = log;
mEquation->Parse(lexer);
if (mEquation->lwing.empty() || mEquation->rwing.empty()) {
mIncorrect = true;
}
else mIncorrect = false;
}
Equation * Solver::Solve() {
if (mIncorrect) return nullptr;
// Break Brackets
// Lwing
mEquation->lwing = RemoveBrackets(mEquation->lwing);
// Rwing
mEquation->rwing = RemoveBrackets(mEquation->rwing);
if (mEquation->lwing.empty() ||
mEquation->rwing.empty())
return {};
// Add operators
mEquation->lwing = AddNonEssientalOps(mEquation->lwing);
mEquation->rwing = AddNonEssientalOps(mEquation->rwing);
// Remove Exponenets
// Lwing
for (int i = 0; i < mEquation->lwing.size(); i++) {
if (mEquation->lwing[i]->mType == TermTypes::Const) {
mEquation->lwing[i] = QMEvalHelper::ReducePower(mEquation->lwing[i])[0];
}
}
// Rwing
for (int i = 0; i < mEquation->rwing.size(); i++) {
if (mEquation->rwing[i]->mType == TermTypes::Const) {
mEquation->rwing[i] = QMEvalHelper::ReducePower(mEquation->rwing[i])[0];
}
}
// Evaluate
mEquation->lwing = evaluate(mEquation->lwing);
mEquation->rwing = evaluate(mEquation->rwing);
// Put vars on one side and consts on another
mEquation = PutVarsInOneSide(mEquation);
mEquation = PutConstsInOneSide(mEquation);
@ -22,6 +60,21 @@ Equation * Solver::Solve() {
return mEquation;
}
bool Solver::CheckEqu(string equation) {
if (!isContain(equation, '=')) {
log->operator<< ("Must Have Equal Sign for Correct Equation!");
system("PAUSE");
exit(0);
}
Equation* equ = new Equation();
lexertk::generator gen;
gen.process(equation);
equ->Parse(gen);
return CheckValidOps(equ);
}
vector<Term*> Solver::FlipTermSigns(vector<Term*> terms) {
vector<Term*> res;
@ -34,8 +87,8 @@ vector<Term*> Solver::FlipTermSigns(vector<Term*> terms) {
if (brack->mConstant == nullptr) {
brack->mConstant = new Constant(-1, 1);
}
else
brack->mConstant->mValue = -brack->mConstant->mValue;
else
brack->mConstant->mValue = -brack->mConstant->mValue;
res.push_back(brack);
}
else {
@ -49,21 +102,59 @@ vector<Term*> Solver::FlipTermSigns(vector<Term*> terms) {
}
Equation * Solver::ApplyDiversionCalcs(Equation * equ) {
// Situations
// Situations:
// 2x = 50 -> x = 50/2, applies only if one var
// 4/3x=4 -> 4=4*4x -> 12x=4 -> x=4/12
auto lwing = RemNonEssientalOps(equ->lwing);
auto rwing = RemNonEssientalOps(equ->rwing);
auto lwing = RemoveBundle(equ->lwing);
auto rwing = RemoveBundle(equ->rwing);
if (lwing.size() == 3) {
if (rwing.size() == 1) {
if (lwing[1]->mOperator == '/') {
auto nomin = lwing[0];
auto domin = lwing[2];
auto right = rwing[0];
auto final_right = QMEvalHelper::Mul(domin, right);
lwing.clear();
rwing.clear();
lwing.push_back(nomin);
for (auto rwing_terms : final_right)
rwing.push_back(rwing_terms);
lwing.swap(rwing);
auto _domin = lwing[0]->mValue;
Bracket* brack = new Bracket();
for (int i = 0; i < rwing.size(); i++)
brack->mTerms.push_back(rwing[i]);
auto term = QMEvalHelper::Div(brack, new Constant(_domin, 1));
rwing.clear();
rwing = term;
lwing[0]->mValue = 1;
equ->lwing = lwing;
equ->rwing = rwing;
return equ;
}
}
}
lwing = RemNonEssientalOps(equ->lwing);
rwing = RemNonEssientalOps(equ->rwing);
if (lwing.size() == 1) {
// Check if x's coeffiecent is higher than 1 or lower
if (lwing[0]->mValue != 1 && lwing[0]->mPower == 1) {
// situation of "2x = 50 -> x = 50/2" is confirmed
auto domin = lwing[0]->mValue;
Bracket* brack = new Bracket();
for (int i = 0; i < rwing.size(); i++)
brack->mTerms.push_back(rwing[i]);
auto term = QMEvalHelper::Div(brack, new Constant(domin));
auto term = QMEvalHelper::Div(brack, new Constant((long double)domin, 1));
rwing.clear();
rwing = term;
lwing[0]->mValue = 1;
@ -79,59 +170,85 @@ Equation * Solver::ApplyDiversionCalcs(Equation * equ) {
bool Solver::CheckValidOps(Equation * equ) {
// Check Lwing
for (int i = 0; i < equ->lwing.size() - 1; i++) {
auto term = equ->lwing[i];
if (term->mType == TermTypes::Op) {
if (i == 0) {
if (term->mOperator == '/' || term->mOperator == '*') {
cout << "Can't have division or multiplication at the begining!" << endl;
system("PUASE");
exit(0);
if (!equ->lwing.empty()) {
// Check Ending
if (equ->lwing[equ->lwing.size() - 1]->mType == TermTypes::Op) {
log->operator<<("Can't have operatos at the end!");
return false;
}
for (int i = 0; i < equ->lwing.size() - 1; i++) {
auto term = equ->lwing[i];
if (term->mType == TermTypes::Op) {
if (i == 0) {
if (term->mOperator == '/' || term->mOperator == '*') {
log->operator<<("Can't have division or multiplication at the begining!");
return false;
}
continue;
}
continue;
}
auto before_Term = equ->lwing[i - 1];
auto after_Term = equ->lwing[i + 1];
auto before_Term = equ->lwing[i - 1];
auto after_Term = equ->lwing[i + 1];
if (before_Term->mType == TermTypes::Op ||
after_Term->mType == TermTypes::Op) {
cout << "Can't have trialing operators!" << endl;
system("PUASE");
exit(0);
if (before_Term->mType == TermTypes::Op ||
after_Term->mType == TermTypes::Op) {
log->operator<<("Can't have trialing operators!");
return false;
}
}
}
}
// Check Rwing
for (int i = 0; i < equ->rwing.size() - 1; i++) {
auto term = equ->rwing[i];
if (term->mType == TermTypes::Op) {
if (i == 0) {
if (term->mOperator == '/' || term->mOperator == '*') {
cout << "Can't have division or multiplication at the begining!" << endl;
if (!equ->rwing.empty()) {
// Check Ending
if (equ->rwing[equ->rwing.size() - 1]->mType == TermTypes::Op) {
log->operator<<("Can't have operatos at the end!");
return false;
}
for (int i = 0; i < equ->rwing.size() - 1; i++) {
auto term = equ->rwing[i];
if (term->mType == TermTypes::Op) {
if (i == 0) {
if (term->mOperator == '/' || term->mOperator == '*') {
log->operator<<("Can't have division or multiplication at the begining!");
system("PUASE");
exit(0);
}
continue;
}
auto before_Term = equ->rwing[i - 1];
auto after_Term = equ->rwing[i + 1];
if (before_Term->mType == TermTypes::Op ||
after_Term->mType == TermTypes::Op) {
log->operator<<("Can't have trialing operators!");
system("PUASE");
exit(0);
}
continue;
}
auto before_Term = equ->rwing[i - 1];
auto after_Term = equ->rwing[i + 1];
if (before_Term->mType == TermTypes::Op ||
after_Term->mType == TermTypes::Op) {
cout << "Can't have trialing operators!" << endl;
system("PUASE");
exit(0);
}
}
}
return true;
}
bool Solver::CheckValidOps(vector<Term*> terms) {
Equation* equ = new Equation();
equ->lwing = terms;
return CheckValidOps(equ);
}
bool Solver::IsVarAval(vector<Term*> terms) {
for (auto term : terms)
if (term->mType == TermTypes::Var)
return true;
return false;
}
Equation * Solver::PutVarsInOneSide(Equation * equ) {
Equation* res = new Equation();
@ -228,13 +345,16 @@ Equation * Solver::PutConstsInOneSide(Equation * equ) {
if (lwing[i]->mType == TermTypes::Bund) {
// check if it has a constant
Bundle* bundle = static_cast<Bundle*>(lwing[i]);
bool contains = false;
for (auto *term : bundle->mTerms)
if (term->mType == TermTypes::Const) { contains = true; continue; }
if (contains)
lwing_const.push_back(i);
continue;
if (!IsVarAval(bundle->mTerms)) {
bool contains = false;
for (auto *term : bundle->mTerms)
if (term->mType == TermTypes::Const) { contains = true; continue; }
if (contains)
lwing_const.push_back(i);
continue;
}
}
if (lwing[i]->mType == TermTypes::Const)
lwing_const.push_back(i);
@ -294,6 +414,11 @@ vector<Term*> Solver::RemNonEssientalOps(vector<Term*> terms) {
vector<Term*> res;
for (int i = 0; i < terms.size(); i++) {
auto term = terms[i];
if (term->mType == TermTypes::Brack) {
auto resultant = RemNonEssientalOps(QMEvalHelper::BreakBracket(static_cast<Bracket*>(term)));
for (auto __term : resultant) res.push_back(__term);
continue;
}
if (term->mType == TermTypes::Op) {
if (term->mOperator == '+') {
auto after_term = terms[i + 1];
@ -303,15 +428,15 @@ vector<Term*> Solver::RemNonEssientalOps(vector<Term*> terms) {
continue;
}
if (term->mOperator == '-') {
auto after_term = terms[i+1];
auto after_term = terms[i + 1];
after_term->mValue = after_term->mValue * -1;
res.push_back(after_term);
i++;
continue;
}
if (term->mOperator == '*') {
auto before_term = *res.end();
auto before_term = *(res.end() - 1);
res.pop_back();
auto after_term = terms[i + 1];
Bundle* bundle = new Bundle();
@ -324,9 +449,9 @@ vector<Term*> Solver::RemNonEssientalOps(vector<Term*> terms) {
}
if (term->mOperator == '/') {
auto before_term = *(--res.end());
auto before_term = *(res.end() - 1);
res.pop_back();
auto after_term = terms[i+1];
auto after_term = terms[i + 1];
Bundle* bundle = new Bundle();
bundle->mTerms.push_back(before_term);
bundle->mTerms.push_back(term);
@ -338,7 +463,7 @@ vector<Term*> Solver::RemNonEssientalOps(vector<Term*> terms) {
}
res.push_back(term);
}
return res;
}
vector<Term*> Solver::AddNonEssientalOps(vector<Term*> terms) {
@ -358,10 +483,13 @@ vector<Term*> Solver::AddNonEssientalOps(vector<Term*> terms) {
}
if (term->mType == TermTypes::Brack) {
res.push_back(term);
auto resultant =
AddNonEssientalOps(QMEvalHelper::BreakBracket(static_cast<Bracket*>(term)));
for (auto *__term : resultant) res.push_back(__term);
continue;
}
// check if term was positive
if (term->mValue > 0) {
res.push_back(new Operator('+'));
@ -401,12 +529,12 @@ vector<Term*> Solver::BundleTermsDuo(vector<Term*> terms) {
if (term->mOperator == '/') {
if (i == 0) {
// invalid cant have division at begining
cout << "Can't have division at begining!" << endl;
log->operator<<("Can't have division at begining!");
system("PAUSE");
exit(0);
}
auto before_term = terms[i-1];
auto after_term = terms[i +1];
auto before_term = terms[i - 1];
auto after_term = terms[i + 1];
Bundle* bundle = new Bundle();
bundle->mTerms.push_back(before_term); // t1
bundle->mTerms.push_back(term); // op
@ -420,11 +548,11 @@ vector<Term*> Solver::BundleTermsDuo(vector<Term*> terms) {
if (term->mOperator == '*') {
if (i == 0) {
// invalid cant have multiplication at begining
cout << "Can't have multiplication at begining!" << endl;
log->operator<<("Can't have multiplication at begining!");
system("PAUSE");
exit(0);
}
auto before_term = terms[i-1];
auto before_term = terms[i - 1];
auto after_term = terms[i + 1];
Bundle* bundle = new Bundle();
bundle->mTerms.push_back(before_term); // t1
@ -459,7 +587,7 @@ vector<Term*> Solver::BundleTermsTri(vector<Term*> terms) {
if (term->mOperator == '/') {
if (i == 0) {
// invalid cant have division at begining
cout << "Can't have division at begining!" << endl;
log->operator<<("Can't have division at begining!");
system("PUASE");
exit(0);
}
@ -478,7 +606,7 @@ vector<Term*> Solver::BundleTermsTri(vector<Term*> terms) {
if (term->mOperator == '*') {
if (i == 0) {
// invalid cant habe multiplication at begining
cout << "Can't have multiplication at beginign!" << endl;
log->operator<<("Can't have multiplication at beginign!");
system("PAUSE");
exit(0);
}
@ -518,7 +646,7 @@ bool Solver::IsEqualBundle(Bundle * b1, Bundle * b2) {
if (b1_copy.size() != b2_copy.size()) return false;
for (int i = 0; i < b1_copy.size(); i++)
if (!QMEvalHelper::IsEquTerms(b1_copy[i], b2_copy[i]))
if (!QMEvalHelper::IsEquTerms(b1_copy[i], b2_copy[i]))
return false;
return true;

View File

@ -1,8 +1,8 @@
#ifndef SOLVER_H
#define SOLVER_H
#pragma once
#include "../Equations.h"
#include "../defines.h"
#include "../Equations.h"
#include "../terms/Brackets.h"
#include "../terms/Constant.h"
#include "../terms/Equal.h"
@ -20,19 +20,61 @@
class Solver {
public:
Solver(LOG* _log = nullptr) {
log = _log;
}
void Parse(string equation);
Equation* Solve();
bool CheckEqu(string equation);
bool CheckValidOps(Equation* equ);
bool CheckValidOps(vector<Term*> terms);
vector<Term*> RemoveBrackets(vector<Term*> terms) {
vector<Term*> res;
for (int i = 0; i < terms.size(); i++) {
auto term = terms[i];
if (terms[i]->mType == TermTypes::Brack) {
auto _terms = QMEvalHelper::BreakBracket(static_cast<Bracket*>(term));
if (!CheckValidOps(_terms)) {
return {};
}
_terms = RemoveBrackets(_terms);
for (auto item : _terms) res.push_back(item);
}
else
res.push_back(term);
}
return res;
}
public: // PRIVATE MEMBERS TODO: MARK PRIVATE IN FINAL BUILD
Equation* mEquation = nullptr;
bool mIncorrect = false;
LOG* log = nullptr;
private: // Mathematics Side Class Todo: Mark Private in final build
vector<Term*> FlipTermSigns(vector<Term*> terms);
Equation* ApplyDiversionCalcs(Equation* equ);
private: // Program Side Calcs TODO: MARK PRIVATE IN FINAL BUILD
bool CheckValidOps(Equation* equ);
public: // Program Side Calcs TODO: MARK PRIVATE IN FINAL BUILD
bool IsVarAval(vector<Term*> terms);
vector<Term*> RemoveBundle(vector<Term*> res) {
vector<Term*> final_res;
for (int i = 0; i < res.size(); i++) {
if (res[i]->mType == TermTypes::Bund) {
auto result = BreakBundle(static_cast<Bundle*>(res[i]));
for (int j = 0; j < result.size(); j++)
final_res.push_back(result[j]);
}
else
final_res.push_back(res[i]);
}
return final_res;
}
Equation* PutVarsInOneSide(Equation* equ);
Equation* PutConstsInOneSide(Equation* equ);

View File

@ -48,12 +48,16 @@ vector<Term*> QMEvalHelper::BreakBracket(Bracket * brack, bool order, Identifier
for (int i = 0; i < brack->mTerms.size(); i++)
res.push_back(brack->mTerms[i]);
}
for (int i = 0; i < brack->mTerms.size(); i++) {
auto returns = Mul(brack->mConstant, brack->mTerms[i]);
for (int j = 0; j < returns.size(); j++)
res.push_back(returns[j]);
}
else
for (int i = 0; i < brack->mTerms.size(); i++) {
if (brack->mTerms[i]->mType != TermTypes::Op) {
auto returns = Mul(brack->mConstant, brack->mTerms[i]);
for (int j = 0; j < returns.size(); j++)
res.push_back(returns[j]);
}
else
res.push_back(brack->mTerms[i]);
}
return res;
}
@ -107,7 +111,7 @@ bool QMEvalHelper::IsHigherSig(Term * t1, Term * t2) { // x^2 > x : true
return t1->mValue >= t2->mValue;
}
// if t1 has higher or equal power
if (t1->mPower >= t2->mPower)
if (t1->mPower >= t2->mPower)
return true;
else return false; // t2 is higher
}
@ -174,7 +178,7 @@ vector<Term*> QMEvalHelper::Add(Term * t1, Term * t2, Identifier_t order) {
// check if one of the terms were brackets
if (IsBracket(t1) || IsBracket(t2)) {
// check which term is bracket
if (IsBracket(t1) && !IsBracket(t2)) {
if (IsBracket(t1) && IsBracket(t2)) {
auto brokenbrack = BreakBracket(convertToBracket(t1));
auto brokenbrack2 = BreakBracket(convertToBracket(t2));
for (int i = 0; i < brokenbrack2.size(); i++)
@ -243,7 +247,6 @@ vector<Term*> QMEvalHelper::Add(Term * t1, Term * t2, Identifier_t order) {
vector<Term*> QMEvalHelper::Sub(Term * t1, Term * t2, Identifier_t order) {
vector<Term*> res;
// check if one of the terms were brackets
if (IsBracket(t1) || IsBracket(t2)) {
// check which term is bracket
@ -325,7 +328,7 @@ vector<Term*> QMEvalHelper::Mul(Term * t1, Term * t2, Identifier_t order) {
// brack, var
// brack, const
if (IsBracket(t1) || IsBracket(t2)) {
if (IsBracket(t1) && IsBracket(t2)) {
auto t1_brokenbrack = BreakBracket(convertToBracket(t1), true, order);
auto t2_brokenbrack = BreakBracket(convertToBracket(t2), true, order);
@ -539,8 +542,6 @@ bool QMEvalHelper::TermsMatch(vector<Term*> terms1, vector<Term*> terms2) {
}
// WARNING: Make sure that t1 and t2 are in the simplest form.
vector<Term*> QMEvalHelper::Div(Term * t1, Term * t2, Identifier_t order) {
// Check if division is solvable
if (IsDivSolvable(t1, t2)) {
// only two situations
@ -615,12 +616,7 @@ vector<Term*> QMEvalHelper::Div(Term * t1, Term * t2, Identifier_t order) {
auto t1_const = convertToConstant(ReducePower(t1)[0]);
auto t2_var = convertToVariable(t2);
Variable* var = new Variable();
var->mVariable = t2_var->mVariable;
var->mValue = t1_const->mValue / t2_var->mValue;
var->mPower = t2_var->mPower;
return { var };
return { t1_const, new Operator('/'), t2_var };
}
else if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Const) {
// var / const

View File

@ -91,9 +91,52 @@ static vector<Term*> getPool() {
return res;
}
static vector<Term*> evaluateRight(vector<Term*> terms) {
TermPool mPool;
mPool.set(terms);
// Step 1:
// Reduce Powers except for variables
for (int i = 0; i < mPool.size(); i++)
if (mPool[i]->mType == TermTypes::Const)
*mPool[i] = *QMEvalHelper::ReducePower(mPool[i])[0];
// Step 2:
// Remove begining sign, if any
if (mPool[0]->mType == TermTypes::Op) {
auto op = mPool.pop_back(); // remove op
auto res = *mPool.begin();
res->mValue = res->mValue * (op->mOperator == '+') ? 1 : -1; // multiply
mPool.pop_front(); // remove term going to be modified
mPool.push_front(res);
}
// Step 3:
// Generate ExpressionTree
ExprTreeReversed tree;
tree.setPool(mPool.vec());
tree.GenerateTree();
// Step 4: Evaluate!!!
mPool.set(solveNode(tree.getHead()));
vector<Term*> res;
for (int i = 0; i < mPool.size(); i++)
res.push_back(mPool[i]);
return res;
}
static vector<Term*> evaluate(vector<Term*> term) {
if (term.empty()) return term;
mPool.set(term);
evaluate();
auto second_pool = evaluateRight(term);
if (second_pool.size() < mPool.size()) {
mPool.set(second_pool);
}
return getPool();
}

View File

@ -101,3 +101,111 @@ void ExprTree::_print(const std::string prefix, const TreeNode* node, bool isLef
_print(prefix + (isLeft ? "| " : " "), node->_right, false);
}
}
void ExprTreeReversed::setPool(vector<Term*> pool) {
mPool.set(pool);
mHead = new TreeNode();
}
void ExprTreeReversed::GenerateTree() {
mHead = _genTree(mPool);
}
void ExprTreeReversed::print() {
_print("", mHead, false);
}
TreeNode * ExprTreeReversed::_genTree(TermPool pool) {
if (pool.size() == 0) return nullptr;
if (pool.size() == 1) {
TreeNode* node = new TreeNode();
node->_term = pool[0];
node->_left = nullptr;
node->_right = nullptr;
return node;
}
// Number operations
std::vector<pair<int, int>> operators;
int counter = 0;
// DIV, MUL first
for (int i = pool.size()-1; i != 0; i--) {
if (pool[i]->mType == TermTypes::Op) {
if (pool[i]->mOperator == '/') {
pair<int, int> resultant;
resultant.first = i;
resultant.second = counter++;
operators.push_back(resultant);
}
if (pool[i]->mOperator == '*') {
pair <int, int> resultant;
resultant.first = i;
resultant.second = counter++;
operators.push_back(resultant);
}
}
}
// ADD, SUB Second
for (int i = pool.size() - 1; i != 0; i--) {
if (pool[i]->mType == TermTypes::Op) {
if (pool[i]->mOperator == '+') {
pair<int, int> resultant;
resultant.first = i;
resultant.second = counter++;
operators.push_back(resultant);
}
else if (pool[i]->mOperator == '-') {
pair<int, int> resultant;
resultant.first = i;
resultant.second = counter++;
operators.push_back(resultant);
}
}
}
stable_sort(operators.begin(), operators.end(),
[this](pair<int, int> arg1, pair<int, int> arg2) {
return arg1.second < arg2.second;
});
// Split upon op, recurse
TermPool left, right;
// dont get the op to left
auto ptr1 = operators[operators.size() - 1].first;
left.set(
pool.getRange(0, ptr1 - 1)
);
// dont get the op to right
right.set(
pool.getRange(ptr1 + 1, pool.size() - 1)
);
// get the op here
Term* op = pool[left.size()];
TreeNode* node = new TreeNode();
node->_term = op;
node->_left = _genTree(left);
node->_right = _genTree(right);
return node;
}
void ExprTreeReversed::_print(const std::string prefix, const TreeNode * node, bool isLeft)
{
if (node != nullptr) {
cout << prefix;
cout << (isLeft ? "|--" : "^--");
// print the value of the node
cout << node->_term->to_str() << endl;
_print(prefix + (isLeft ? "| " : " "), node->_left, true);
_print(prefix + (isLeft ? "| " : " "), node->_right, false);
}
}

View File

@ -40,4 +40,24 @@ private:
};
class ExprTreeReversed {
public:
void setPool(vector<Term*> pool);
void GenerateTree();
void print();
TreeNode* getHead() { return mHead; }
private:
TreeNode* _genTree(TermPool pool);
void _print(const std::string prefix, const TreeNode* node, bool isLeft);
TreeNode* mHead = nullptr;
TermPool mPool;
};
#endif // !EXPR_TREE_H

View File

@ -67,6 +67,8 @@ static lexertk::generator retriveSubLexer(lexertk::generator gen, Token tok) {
// Paranthesis(bool is, int _pos) : isOpening(is), pos(_pos) {}
//};
static LOG* tok_log = nullptr;
vector<Term*> tokenize(lexertk::generator lexed);
static Bracket* tokenize_bracket(lexertk::generator gen, Token* token, string coefficient) {
@ -78,19 +80,21 @@ static Bracket* tokenize_bracket(lexertk::generator gen, Token* token, string co
// DETERMINE THE ENDING OF THE BRACKETS
int counter = 0;
bool state = false;
int index = token->begin;
do {
if (isBracketsOpening(gen[index].value[0])) {
counter++;
state = true;
}
else if (isBracketsClosing(gen[index].value[0])) {
counter--;
state = false;
}
index++;
} while (!(!state && counter == 0));
if (index > gen.size()) {
// end of string
tok_log->operator<<("Unbalanced Paranthesis!");
return nullptr;
}
} while (counter != 0);
bracks = retriveSubLexer(gen, Token(token->begin, index - 1));
token->end = index - 1; // to make sure we move the token pointer to the end of bracks
@ -101,12 +105,15 @@ static Bracket* tokenize_bracket(lexertk::generator gen, Token* token, string co
// Tokenize its term
// first make sure it is not empty
if (bracks.empty()) {
cout << "Brackets can't be empty!" << endl;
system("PAUSE");
exit(0);
tok_log->operator<<("Bracket can't be empty!");
return nullptr;
}
// tokenize terms
auto terms = tokenize(bracks);
if (terms.empty()) {
tok_log->operator<<("Failed to tokenize bracket's coefficient!");
return nullptr;
}
result->mTerms = terms;
@ -127,44 +134,50 @@ static vector<Term*> combineBrackets(vector<Term*> terms) {
if (term->mType == TermTypes::Op &&
(term->mOperator == '-' || term->mOperator == '+')) {
// if after it was a number
if (terms[i + 1]->mType == TermTypes::Const || terms[i + 1]->mType == TermTypes::Var) {
// check for safety
if (!(terms.size() <= i + 2))
// if after it was a bracket too
if (terms[i + 2]->mType == TermTypes::Brack) {
if (i + 1 >= terms.size()) {
// cant check after it
result.push_back(terms[i]);
continue;
}
else
// if after it was a number
if (terms[i + 1]->mType == TermTypes::Const || terms[i + 1]->mType == TermTypes::Var) {
// check for safety
if (!(terms.size() <= i + 2))
// if after it was a bracket too
if (terms[i + 2]->mType == TermTypes::Brack) {
// if so combine the terms
Bracket* brack = new Bracket();
brack->mTerms = static_cast<Bracket*>(terms[i + 2])->mTerms;
auto constant = static_cast<Bracket*>(terms[i + 2])->mConstant;
constant->mValue *= (term->mOperator == '+') ? +1 : -1;
brack->mConstant = constant;
result.push_back(brack);
i += 2;
continue;
}
}
else {
if (terms[i + 1]->mType == TermTypes::Brack) {
// if so combine the terms
Bracket* brack = new Bracket();
brack->mTerms = static_cast<Bracket*>(terms[i + 2])->mTerms;
auto constant = static_cast<Bracket*>(terms[i + 2])->mConstant;
constant->mValue *= (term->mOperator == '+') ? +1 : -1;
brack->mConstant = constant;
brack->mTerms = static_cast<Bracket*>(terms[i + 1])->mTerms;
auto constant = static_cast<Bracket*>(terms[i + 1])->mConstant;
if (constant == nullptr) { // 1
Constant* Const = new Constant();
if (term->mOperator == '+')
Const->mValue = 1;
else Const->mValue = -1;
}
else {
constant->mValue *= (term->mOperator == '+') ? +1 : -1;
brack->mConstant = constant;
}
result.push_back(brack);
i += 2;
i += 1;
continue;
}
}
else {
if (terms[i + 1]->mType == TermTypes::Brack) {
// if so combine the terms
Bracket* brack = new Bracket();
brack->mTerms = static_cast<Bracket*>(terms[i + 1])->mTerms;
auto constant = static_cast<Bracket*>(terms[i + 1])->mConstant;
if (constant == nullptr) { // 1
Constant* Const = new Constant();
if (term->mOperator == '+')
Const->mValue = 1;
else Const->mValue = -1;
}
else {
constant->mValue *= (term->mOperator == '+') ? +1 : -1;
brack->mConstant = constant;
}
result.push_back(brack);
i += 1;
continue;
}
}
}
result.push_back(term);
}
@ -217,6 +230,16 @@ static vector<Term*> tokenize(lexertk::generator lexed) {
Token tok;
tok.begin = i;
if (lex.value == "^") {
// invalid
tok_log->operator<<("There can't be a stranded power sign!");
return {};
}
if (lex.value == ")") {
// invalid
tok_log->operator<<("There can't be an ending without a begining!");
return {};
}
if (is_all_digits(lex.value)) {
// number
@ -230,17 +253,27 @@ static vector<Term*> tokenize(lexertk::generator lexed) {
// powers ONLY can be numbers no evaluation is done in the power
// ex: 5^2*3 // the expression will be 5 by 5 then multiply 3
if (!is_all_digits(lexed[i + 3].value)) {
cout << "ONLY numbers are allowed in powers!" << endl;
system("PAUSE");
exit(0);
tok_log->operator<<("ONLY numbers are allowed in powers!");
return {};
/////// ENDING OF TREE
}
// check for bracket
if (lexed[i + 4].value == "(") {
// check for brackets at the end
if (i + 5 >= lexed.size()) {
// invalid, having opening bracks at the end
tok_log->operator<<("There can't be opening bracks at the end!");
return {};
}
// bracket detected
tok.begin += 4; // consume coefficient
result.push_back(tokenize_bracket(lexed, &tok, lex.value + after_lex.value + lexed[i + 2].value + lexed[i + 3].value));
auto brack = tokenize_bracket(lexed, &tok, lex.value + after_lex.value + lexed[i + 2].value + lexed[i + 3].value);
if (brack == nullptr) {
return {};
}
result.push_back(brack);
/////// ENDING OF TREE
}
else {
@ -255,9 +288,19 @@ static vector<Term*> tokenize(lexertk::generator lexed) {
else {
if (lexed[i + 2].value == "(") {
// check for brackets at the end
if (i + 3 >= lexed.size()) {
// invalid, having opening bracks at the end
tok_log->operator<<("There can't be opening bracks at the end!");
return {};
}
// bracket detected
tok.begin += 2;
result.push_back(tokenize_bracket(lexed, &tok, lex.value + after_lex.value));
auto brack = tokenize_bracket(lexed, &tok, lex.value + after_lex.value);
if (brack == nullptr) {
return {};
}
result.push_back(brack);
/////// ENDING OF TREE
}
else {
@ -271,10 +314,20 @@ static vector<Term*> tokenize(lexertk::generator lexed) {
}
}
else if (isBrackets(after_lex.value[0]) && isBracketsOpening(after_lex.value[0])) {
// check for brackets at the end
if (i + 2 >= lexed.size()) {
// invalid, having opening bracks at the end
tok_log->operator<<("There can't be opening bracks at the end!");
return {};
}
// check for brackets,
// if so tokenize the brackets
tok.begin++; // consume the coefficient
result.push_back(tokenize_bracket(lexed, &tok, lex.value));
auto brack = tokenize_bracket(lexed, &tok, lex.value);
if (brack == nullptr) {
return {};
}
result.push_back(brack);
/////// ENDING OF TREE
}
else if (isPower(after_lex.value[0])) {
@ -282,17 +335,26 @@ static vector<Term*> tokenize(lexertk::generator lexed) {
// if so read the power and its constant
// powers ONLY can be numbers no evaluation is done in the power
// ex: 5^2*3 // the expression will be 5 by 5 then multiply 3
if (!is_all_digits(lexed[i + 2].value)) {
cout << "ONLY numbers are allowed in powers!" << endl;
system("PAUSE");
exit(0);
if (!is_all_digits(lexed[i + 3].value)) {
tok_log->operator<<("ONLY numbers are allowed in powers!");
return {};
/////// ENDING OF TREE
}
// check for brackets
if (lexed[i + 3].value == "(") {
// check for brackets at the end
if (i + 5 >= lexed.size()) {
// invalid, having opening bracks at the end
tok_log->operator<<("There can't be opening bracks at the end!");
return {};
}
tok.begin += 3;
result.push_back(tokenize_bracket(lexed, &tok, lex.value + after_lex.value + lexed[i + 2].value));
auto brack = tokenize_bracket(lexed, &tok, lex.value + after_lex.value + lexed[i + 2].value);
if (brack == nullptr) {
return {};
}
result.push_back(brack);
}
else {
Constant* Const = nullptr;
@ -319,15 +381,14 @@ static vector<Term*> tokenize(lexertk::generator lexed) {
if (isPower(after_lex.value[0])) {
// powers ONLY can be numbers no evaluation is done in the power
// ex: 5^2*3 // the expression will be 5 by 5 then multiply 3
if (!is_all_digits(lexed[i + 2].value)) {
cout << "ONLY numbers are allowed in powers!" << endl;
system("PAUSE");
exit(0);
if (!is_all_digits(lexed[i + 3].value)) {
tok_log->operator<<("ONLY numbers are allowed in powers!");
return {};
/////// ENDING OF TREE
}
Variable* Var = nullptr;
Var = new Variable(1.0, lex.value[0], lexed[i + 2].value[0]);
Var = new Variable(1.0, lex.value[0], atof(&lexed[i + 3].value[0]));
result.push_back(Var);
tok.end = i + 2;
/////// ENDING OF TREE
@ -342,8 +403,17 @@ static vector<Term*> tokenize(lexertk::generator lexed) {
}
}
else if (isBracketsOpening(lex.value[0])) {
// check for brackets at the end
if (i+1 >= lexed.size()) {
// invalid, having opening bracks at the end
tok_log->operator<<("There can't be opening bracks at the end!");
return {};
}
// bracket
result.push_back(tokenize_bracket(lexed, &tok, ""));
auto brack = tokenize_bracket(lexed, &tok, "");
if (brack == nullptr)
return {};
result.push_back(brack);
}
else if (isArithmitic(lex.value[0])) {
// operator
@ -352,7 +422,6 @@ static vector<Term*> tokenize(lexertk::generator lexed) {
op = new Operator(lex.value[0]);
result.push_back(op);
tok.end = i;
}
else if (isEqualChar(lex.value[0])) {
// equal sign

25
QuicMaf/qm.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef QM_H
#define QM_H
#include "Log.h"
#include "maths/defines.h"
#include "maths/Equations.h"
#include "maths/tokenizer.h"
#include "maths/terms/Brackets.h"
#include "maths/terms/Bundle.h"
#include "maths/terms/Constant.h"
#include "maths/terms/Equal.h"
#include "maths/terms/Operator.h"
#include "maths/terms/Paranthesis.h"
#include "maths/terms/Term.h"
#include "maths/terms/Variable.h"
#include "maths/solver/Solver.h"
#include "maths/solver/term_rewriter/QMEvalHelper.h"
#include "maths/solver/term_rewriter/QMEvaluator.h"
#include "maths/solver/term_rewriter/ds/ExprTree.h"
#include "maths/solver/term_rewriter/ds/TermPool.h"
#endif // !QM_H

@ -1 +0,0 @@
Subproject commit 053d5ad24d9a58063f2bd71c186cb6adf807ea0a

Binary file not shown.

Binary file not shown.

View File

@ -1,19 +0,0 @@
 QMReducerHelper.cpp
r:\projects\quicmaf\quicmaf\maths\terms\term.h(10): warning C4309: 'default argument': truncation of constant value
r:\projects\quicmaf\quicmaf\maths\terms\term.h(22): warning C4305: 'initializing': truncation from 'int' to 'CValue'
r:\projects\quicmaf\quicmaf\maths\terms\term.h(22): warning C4309: 'initializing': truncation of constant value
r:\projects\quicmaf\quicmaf\maths\terms\term.h(24): warning C4305: 'initializing': truncation from 'int' to 'CValue'
r:\projects\quicmaf\quicmaf\maths\terms\term.h(24): warning C4309: 'initializing': truncation of constant value
r:\projects\quicmaf\quicmaf\maths\terms\variable.h(11): warning C4309: 'default argument': truncation of constant value
r:\projects\quicmaf\quicmaf\maths\tokenizer.h(99): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
r:\projects\quicmaf\quicmaf\maths\solver\term_rewriter\qmruleset.h(34): warning C4267: 'return': conversion from 'size_t' to 'int', possible loss of data
r:\projects\quicmaf\quicmaf\maths\solver\term_rewriter\qmreducerhelper.cpp(445): warning C4244: 'argument': conversion from 'NValue' to 'int', possible loss of data
r:\projects\quicmaf\quicmaf\maths\solver\term_rewriter\qmreducerhelper.cpp(453): warning C4244: 'argument': conversion from 'NValue' to 'int', possible loss of data
r:\projects\quicmaf\quicmaf\maths\solver\term_rewriter\qmreducerhelper.cpp(464): warning C4244: 'argument': conversion from 'NValue' to 'int', possible loss of data
r:\projects\quicmaf\quicmaf\maths\solver\term_rewriter\qmreducerhelper.cpp(472): warning C4244: 'argument': conversion from 'NValue' to 'int', possible loss of data
Generating code
2 of 790 functions ( 0.3%) were compiled, the rest were copied from previous compilation.
0 functions were new in current compilation
1 functions had inline decision re-evaluated but remain unchanged
Finished generating code
QuicMaf.vcxproj -> R:\Projects\QuicMaf\x64\Release\QuicMaf.exe

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

66
QuicMafGui/Dashboard.cpp Normal file
View File

@ -0,0 +1,66 @@
#include "Dashboard.h"
Dashboard::Dashboard(LOG* _log) :
wxFrame(nullptr, wxID_ANY, "QuicMaf", wxDefaultPosition,
wxSize(230, 200), wxDEFAULT_FRAME_STYLE & ~wxMAXIMIZE_BOX & ~wxMINIMIZE_BOX) {
this->SetMinSize(this->GetSize());
this->SetMaxSize(this->GetSize());
CreateControls();
SizeControls();
Center();
log = _log;
}
void Dashboard::CreateControls() {
mPanel = new wxPanel(this, dsh_panel);
mEvalPg = new wxButton(mPanel, dsh_eval_btn, "Evaluate");
mSolverPg = new wxButton(mPanel, dsh_solver_btn, "Solver");
}
void Dashboard::SizeControls() {
mEvalPg->SetSize(wxSize(
GetClientSize().x-4,
(GetClientSize().y / 2) - 4
));
mSolverPg->SetSize(wxSize(
GetClientSize().x-4,
(GetClientSize().y / 2) - 4
));
mEvalPg->SetPosition(
wxPoint(
(GetClientSize().x/2)-(mEvalPg->GetSize().x/2),
0.15*GetClientSize().y
)
);
mEvalPg->SetPosition(wxPoint(2, 0));
mSolverPg->SetPosition(wxPoint(
2,
mEvalPg->GetSize().y + 4
));
}
void Dashboard::OnEvalBtn(wxCommandEvent & evt) {
this->Hide();
Evaluator *eval = new Evaluator(this, log);
eval->Show(true);
}
void Dashboard::OnSolverBtn(wxCommandEvent & evt) {
this->Hide();
Solve* solve = new Solve(this, log);
solve->Show(true);
}
BEGIN_EVENT_TABLE(Dashboard, wxFrame)
EVT_BUTTON(dsh_eval_btn, Dashboard::OnEvalBtn)
EVT_BUTTON(dsh_solver_btn, Dashboard::OnSolverBtn)
END_EVENT_TABLE()

34
QuicMafGui/Dashboard.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef DASHBOARD_H
#define DASHBOARD_H
#pragma once
#include <wx/wx.h>
#include "dlgs/evaluator.h"
#include "dlgs/Solve_dlg.h"
class Dashboard : public wxFrame {
public:
Dashboard(LOG* log = nullptr);
void CreateControls();
void SizeControls();
private:
wxDECLARE_EVENT_TABLE();
wxPanel* mPanel = nullptr;
wxButton* mEvalPg = nullptr;
wxButton* mSolverPg = nullptr;
void OnEvalBtn(wxCommandEvent& evt);
void OnSolverBtn(wxCommandEvent& evt);
LOG* log = nullptr;
};
enum {
dsh_panel,
dsh_eval_btn,
dsh_solver_btn
};
#endif // !DASHBOARD_H

Binary file not shown.

View File

@ -0,0 +1,4 @@
r:\projects\quicmaf\quicmafgui\debug\vc141.idb
r:\projects\quicmaf\quicmafgui\debug\vc141.pdb
r:\projects\quicmaf\debug\quicmafgui.pdb
r:\projects\quicmaf\quicmafgui\debug\quicmafgui.tlog\cl.command.1.tlog

View File

@ -0,0 +1,2 @@
 qmgui.cpp
QuicMafGui.vcxproj -> R:\Projects\QuicMaf\Debug\QuicMafGui.exe

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,2 +1,2 @@
#TargetFrameworkVersion=v4.0:PlatformToolSet=v141:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=10.0.17763.0
Release|x64|R:\Projects\QuicMaf\|
Debug|Win32|R:\Projects\QuicMaf\|

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
QuicMafGui/Debug/Source.obj Normal file

Binary file not shown.

BIN
QuicMafGui/Debug/qmgui.obj Normal file

Binary file not shown.

BIN
QuicMafGui/Debug/vc141.idb Normal file

Binary file not shown.

BIN
QuicMafGui/Debug/vc141.pdb Normal file

Binary file not shown.

View File

@ -0,0 +1,176 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{7CDC5570-9785-446C-8CB9-C03E6D98927F}</ProjectGuid>
<RootNamespace>QuicMafGui</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)bin/$(Configuration)-$(Platform)/</OutDir>
<IntDir>$(SolutionDir)bin-int/$(Configuration)-$(Platform)/</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)bin/$(Configuration)-$(Platform)/</OutDir>
<IntDir>$(SolutionDir)bin-int/$(Configuration)-$(Platform)/</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)bin/$(Configuration)-$(Platform)/</OutDir>
<IntDir>$(SolutionDir)bin-int/$(Configuration)-$(Platform)/</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)bin/$(Configuration)-$(Platform)/</OutDir>
<IntDir>$(SolutionDir)bin-int/$(Configuration)-$(Platform)/</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(WXWIN)\include;$(WXWIN)\include\msvc;$(SolutionDir)\QuicMaf</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;WINVER=0x0400;__WXMSW__;_WINDOWS;wxUSE_GUI=1;_UNICODE;_DEBUG;__WXDEBUG__;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
<Link>
<AdditionalDependencies>wxmsw31ud_core.lib;wxbase31ud.lib;comctl32.lib;rpcrt4.lib;winmm.lib;advapi32.lib;wsock32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(WXWIN)\lib\vc_lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Windows</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(WXWIN)\include;$(WXWIN)\include\msvc;$(SolutionDir)\QuicMaf</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PreprocessorDefinitions>WIN32;WINVER=0x0400;__WXMSW__;_WINDOWS;wxUSE_GUI=1;_UNICODE;_DEBUG;__WXDEBUG__;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(WXWIN)\lib\vc_x64_lib;</AdditionalLibraryDirectories>
<AdditionalDependencies>wxmsw31ud_core.lib;wxbase31ud.lib;comctl32.lib;rpcrt4.lib;winmm.lib;advapi32.lib;wsock32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Windows</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(WXWIN)\include;$(WXWIN)\include\msvc;$(SolutionDir)\QuicMaf</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;WINVER=0x0400;__WXMSW__;_WINDOWS;wxUSE_GUI=1;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>wxmsw31u_core.lib;wxbase31u.lib;comctl32.lib;rpcrt4.lib;winmm.lib;advapi32.lib;wsock32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(WXWIN)\lib\vc_lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(WXWIN)\include;$(WXWIN)\include\msvc;$(SolutionDir)\QuicMaf</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PreprocessorDefinitions>WIN32;WINVER=0x0400;__WXMSW__;_WINDOWS;wxUSE_GUI=1;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(WXWIN)\lib\vc_x64_lib;</AdditionalLibraryDirectories>
<AdditionalDependencies>wxmsw31u_core.lib;wxbase31u.lib;comctl32.lib;rpcrt4.lib;winmm.lib;advapi32.lib;wsock32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Dashboard.cpp" />
<ClCompile Include="dlgs\Evaluator.cpp" />
<ClCompile Include="qmgui.cpp" />
<ClCompile Include="dlgs\Solve_dlg.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Dashboard.h" />
<ClInclude Include="dlgs\evaluator.h" />
<ClInclude Include="dlgs\Solve_dlg.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\QuicMaf\QuicMaf.vcxproj">
<Project>{ea73d661-b6eb-4156-ac92-a470a6683307}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="qmgui.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Dashboard.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dlgs\Evaluator.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dlgs\Solve_dlg.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Dashboard.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="dlgs\evaluator.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="dlgs\Solve_dlg.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>true</ShowAllFiles>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,154 @@
#include "evaluator.h"
Evaluator::Evaluator(wxWindow* pId, LOG* _log) :
wxDialog(pId, wxID_ANY, "QuicMaf | Evaluator",
wxDefaultPosition, wxSize(400, 200), wxDEFAULT_FRAME_STYLE & ~wxMAXIMIZE_BOX & ~wxMINIMIZE_BOX) {
CreateControls();
SizeControls();
Center();
log = _log;
solver = new Solver(log);
}
void Evaluator::CreateControls() {
mPanel = new wxPanel(this, eval_panel);
mInput = new wxTextCtrl(mPanel, eval_input);
mOutput = new wxListBox(mPanel, eval_output);
mOutput->Clear();
mOutput->AppendString("Enter an expression to evaluate!");
}
void Evaluator::SizeControls() {
mInput->SetSize(wxSize(
GetClientSize().x-4,
(GetClientSize().y/2)-4
));
mOutput->SetSize(wxSize(
GetClientSize().x-4,
(GetClientSize().y / 2) - 4
));
mInput->SetPosition(wxPoint(2, 0));
mOutput->SetPosition(wxPoint(2, mInput->GetPosition().y+mInput->GetSize().y+4));
}
void Evaluator::OnInputChange(wxCommandEvent & evt) {
// Check for emptyness
if (mInput->GetValue().empty()) {
mOutput->Clear();
mOutput->AppendString("Enter an expression to evaluate!");
return;
}
// Check for blank
if (mInput->GetValue() == " ") {
mOutput->Clear();
mOutput->AppendString("I wonder what a blank evaluates to!");
return;
}
// Check for illegal chars
for (auto c : mInput->GetValue().ToStdString()) {
switch (c) {
case '!':
case '@':
case '#':
case '$':
case '%':
case '&':
case '*':
case '|':
case '{':
case '}':
case '[':
case ']':
case '>':
case '<':
case '~':
case '?':
mOutput->Clear();
mOutput->AppendString("Illegal character!");
return;
break;
default:
break;
}
}
if (CheckExpr(mInput->GetValue().ToStdString())) {
vector<Term*> terms;
string input = mInput->GetValue().ToStdString();
lexertk::generator gen;
gen.process(input);
tok_log = log;
terms = tokenize(gen);
if (terms.empty()) {
// error occured
mOutput->Clear();
for (auto item : *log->qm_log)
mOutput->AppendString(item);
log->qm_log->clear();
return;
}
if (!solver->CheckValidOps(terms)) {
mOutput->Clear();
mOutput->AppendString("Operators are not correct!");
}
else {
// check for ending operators
if (terms[terms.size() - 1]->mType == TermTypes::Op) {
// there can't be ending operators
mOutput->Clear();
mOutput->AppendString("Operators can't be at the end!");
}
else {
// Break brackets
terms = solver->RemoveBrackets(terms);
// Remove Exponents
for (int i = 0; i < terms.size(); i++) {
if (terms[i]->mType == TermTypes::Const) {
terms[i] = QMEvalHelper::ReducePower(terms[i])[0];
}
}
terms = evaluate(terms);
terms = solver->AddNonEssientalOps(terms);
if (terms.empty()) {
// error occured
mOutput->Clear();
for (auto item : *log->qm_log)
mOutput->AppendString(item);
log->qm_log->clear();
return;
}
string output = "";
for (int i = 0; i < terms.size(); i++)
output.append(terms[i]->to_str());
mOutput->Clear();
mOutput->AppendString(output);
}
}
}
else {
mOutput->Clear();
mOutput->AppendString("There can't be an equal sign!");
}
}
void Evaluator::OnClose(wxCloseEvent & evt) {
this->GetParent()->Show(true);
Destroy();
}
bool Evaluator::CheckExpr(string str) {
if (isContain(str, '=')) return false;
}
BEGIN_EVENT_TABLE(Evaluator, wxDialog)
EVT_TEXT(eval_input, Evaluator::OnInputChange)
EVT_CLOSE(Evaluator::OnClose)
END_EVENT_TABLE()

View File

@ -0,0 +1,134 @@
#include "Solve_dlg.h"
Solve::Solve(wxWindow* pID, LOG* _log)
: wxDialog(pID, wxID_ANY,
"QuicMaf | Solver", wxDefaultPosition,
wxSize(400, 200), wxDEFAULT_FRAME_STYLE & ~wxMAXIMIZE_BOX & ~wxMINIMIZE_BOX) {
CreateControls();
SizeControls();
Center();
log = _log;
solver = new Solver(log);
}
void Solve::CreateControls() {
mPanel = new wxPanel(this, solve_panel);
mInput = new wxTextCtrl(mPanel, solve_input);
mOutput = new wxListBox(mPanel, solve_output);
mOutput->Clear();
mOutput->AppendString("Enter an equation to solve!");
}
void Solve::SizeControls() {
mInput->SetSize(wxSize(
GetClientSize().x - 4,
(GetClientSize().y / 2) - 4
));
mOutput->SetSize(wxSize(
GetClientSize().x - 4,
(GetClientSize().y / 2) - 4
));
mInput->SetPosition(wxPoint(2, 0));
mOutput->SetPosition(wxPoint(2, mInput->GetPosition().y + mInput->GetSize().y + 4));
}
void Solve::OnInputChange(wxCommandEvent & evt) {
// Check for emptyness
if (mInput->GetValue().empty()) {
mOutput->Clear();
mOutput->AppendString("Enter an equation to solve!");
return;
}
// Check for blank
if (mInput->GetValue() == " ") {
mOutput->Clear();
mOutput->AppendString("I wonder what a blank evaluates to!");
return;
}
// Check for equal only
if (mInput->GetValue() == "=") {
mOutput->Clear();
mOutput->AppendString("Equal is an Equal.");
return;
}
// Check if there isnt an equal
if (!isContain(mInput->GetValue().ToStdString(), '=')) {
mOutput->Clear();
mOutput->AppendString("There must be an equal sign!");
return;
}
// Check for illegal chars
for (auto c : mInput->GetValue().ToStdString()) {
switch (c) {
case '!':
case '@':
case '#':
case '$':
case '%':
case '&':
case '*':
case '|':
case '{':
case '}':
case '[':
case ']':
case '>':
case '<':
case '~':
case '?':
mOutput->Clear();
mOutput->AppendString("Illegal character!");
return;
break;
default:
break;
}
}
solver->Parse(mInput->GetValue().ToStdString());
auto equ = solver->Solve();
if (equ == nullptr) {
// error occured
mOutput->Clear();
for (auto item : *log->qm_log)
mOutput->AppendString(item);
log->qm_log->clear();
return;
}
if (equ->lwing.empty()) {
mOutput->Clear();
mOutput->AppendString("Left wing must not be empty!");
}
if (equ->rwing.empty()) {
mOutput->Clear();
mOutput->AppendString("Right wing must not be empty!");
}
string str;
for (auto lwing_term : equ->lwing)
str.append(lwing_term->to_str());
str.append("=");
for (auto rwing_term : equ->rwing)
str.append(rwing_term->to_str());
mOutput->Clear();
mOutput->AppendString(str);
}
void Solve::OnClose(wxCloseEvent & evt) {
this->GetParent()->Show(true);
Destroy();
}
BEGIN_EVENT_TABLE(Solve, wxDialog)
EVT_TEXT(solve_input, Solve::OnInputChange)
EVT_CLOSE(Solve::OnClose)
END_EVENT_TABLE()

View File

@ -0,0 +1,35 @@
#ifndef SOLVE_DLG_H
#define SOLVE_DLG_H
#pragma once
#include <wx/wx.h>
#include "qm.h"
class Solve : public wxDialog {
public:
Solve(wxWindow* pID, LOG* log = nullptr);
void CreateControls();
void SizeControls();
private:
wxDECLARE_EVENT_TABLE();
wxPanel *mPanel = nullptr;
wxTextCtrl* mInput = nullptr;
wxListBox* mOutput = nullptr;
void OnInputChange(wxCommandEvent& evt);
void OnClose(wxCloseEvent& evt);
Solver* solver = nullptr;
LOG* log = nullptr;
};
enum {
solve_panel,
solve_input,
solve_output
};
#endif // !SOLVE_DLG

View File

@ -0,0 +1,35 @@
#ifndef EVALUATOR_H
#define EVALUATOR_H
#pragma once
#include <wx/wx.h>
#include "qm.h"
class Evaluator : public wxDialog {
public:
Evaluator(wxWindow* pId, LOG* _log = nullptr);
void CreateControls();
void SizeControls();
private:
wxDECLARE_EVENT_TABLE();
wxPanel* mPanel = nullptr;
wxTextCtrl *mInput = nullptr;
wxListBox *mOutput = nullptr;
void OnInputChange(wxCommandEvent& evt);
void OnClose(wxCloseEvent& evt);
bool CheckExpr(string str);
Solver* solver = nullptr;
LOG* log = nullptr;
};
enum {
eval_panel,
eval_input,
eval_output,
};
#endif // !EVALUATOR_H

17
QuicMafGui/qmgui.cpp Normal file
View File

@ -0,0 +1,17 @@
#include <wx/wx.h>
#include "Dashboard.h"
class MyApp : public wxApp {
public:
virtual bool OnInit();
};
bool MyApp::OnInit() {
LOG* log = new LOG();
Dashboard *dash = new Dashboard(log);
dash->Show(true);
return true;
}
wxIMPLEMENT_APP(MyApp);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.