diff options
Diffstat (limited to 'src/libparser/node')
65 files changed, 6210 insertions, 0 deletions
diff --git a/src/libparser/node/allsamenode.cpp b/src/libparser/node/allsamenode.cpp new file mode 100644 index 0000000..3b2f10f --- /dev/null +++ b/src/libparser/node/allsamenode.cpp @@ -0,0 +1,86 @@ +#include "allsamenode.h" + +AllSameNode::AllSameNode() : m_diceResult(new DiceResult()) +{ + m_result= m_diceResult; +} + +void AllSameNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr != previous) + { + DiceResult* previous_result= dynamic_cast<DiceResult*>(previous->getResult()); + if(nullptr != previous_result) + { + m_result->setPrevious(previous_result); + bool allSame= true; + int i= 0; + qint64 previousValue= 0; + if(previous_result->getResultList().size() < 2) + { + m_errors.insert(Dice::ERROR_CODE::ENDLESS_LOOP_ERROR, + QStringLiteral("T operator must operate on more than 1 die")); + return; + } + for(auto& die : previous_result->getResultList()) + { + if(i == 0) + previousValue= die->getValue(); + Die* tmpdie= new Die(*die); + m_diceResult->insertResult(tmpdie); + die->displayed(); + if(previousValue != die->getValue()) + allSame= false; + ++i; + } + + while(allSame) + { + QList<Die*> list= m_diceResult->getResultList(); + qint64 pValue= 0; + int i= 0; + for(auto& die : list) + { + die->roll(true); + if(i == 0) + pValue= die->getValue(); + if(pValue != die->getValue()) + allSame= false; + ++i; + } + } + } + } + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} + +QString AllSameNode::toString(bool withLabel) const +{ + if(withLabel) + { + return QString("%1 [label=\"AllSameNode\"]").arg(m_id); + } + else + { + return m_id; + } +} + +qint64 AllSameNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_nextNode) + { + priority= m_nextNode->getPriority(); + } + return priority; +} + +ExecutionNode* AllSameNode::getCopy() const +{ + return new AllSameNode(); +} diff --git a/src/libparser/node/allsamenode.h b/src/libparser/node/allsamenode.h new file mode 100644 index 0000000..e5c1dc2 --- /dev/null +++ b/src/libparser/node/allsamenode.h @@ -0,0 +1,33 @@ +#ifndef ALLSAMENODE_H +#define ALLSAMENODE_H + +#include "executionnode.h" + +#include "result/diceresult.h" +#include "validator.h" + +class AllSameNode : public ExecutionNode +{ +public: + AllSameNode(); +// virtual ~AllSameNode(); + + virtual void run(ExecutionNode* previous); + /** + * @brief toString + * @return + */ + virtual QString toString(bool withLabel) const; + /** + * @brief getPriority + * @return + */ + virtual qint64 getPriority() const; + + virtual ExecutionNode* getCopy() const; + +private: + DiceResult* m_diceResult; +}; + +#endif // FILTERNODE_H diff --git a/src/libparser/node/bind.cpp b/src/libparser/node/bind.cpp new file mode 100644 index 0000000..490071f --- /dev/null +++ b/src/libparser/node/bind.cpp @@ -0,0 +1,114 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "bind.h" + +BindNode::BindNode() : m_diceResult(new DiceResult()) +{ + m_result= m_diceResult; +} +void BindNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr == m_previousNode) + return; + + m_result->setPrevious(previous->getResult()); + for(auto start : *m_startList) + { + ExecutionNode* last= getLatestNode(start); + if(nullptr != last) + { + auto tmpResult= last->getResult(); + while(nullptr != tmpResult) + { + DiceResult* dice= dynamic_cast<DiceResult*>(tmpResult); + if(nullptr != dice) + { + m_diceResult->setHomogeneous(false); + for(auto& die : dice->getResultList()) + { + if(!die->hasBeenDisplayed()) + { + Die* tmpdie= new Die(*die); + die->displayed(); + m_diceResult->getResultList().append(tmpdie); + } + } + } + tmpResult= tmpResult->getPrevious(); + } + } + } + + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} +ExecutionNode* BindNode::getLatestNode(ExecutionNode* node) +{ + ExecutionNode* next= node; + while(nullptr != next->getNextNode() && (next->getNextNode() != this)) + { + next= next->getNextNode(); + } + return next; +} +QString BindNode::toString(bool withLabel) const +{ + if(withLabel) + { + return QString("%1 [label=\"Bind Node\"]").arg(m_id); + } + else + { + return m_id; + } +} +qint64 BindNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_previousNode) + { + priority= m_previousNode->getPriority(); + } + return priority; +} +ExecutionNode* BindNode::getCopy() const +{ + BindNode* node= new BindNode(); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} + +std::vector<ExecutionNode*>* BindNode::getStartList() const +{ + return m_startList; +} + +void BindNode::setStartList(std::vector<ExecutionNode*>* startList) +{ + m_startList= startList; +} diff --git a/src/libparser/node/bind.h b/src/libparser/node/bind.h new file mode 100644 index 0000000..71bbfb0 --- /dev/null +++ b/src/libparser/node/bind.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef BINDNODE_H +#define BINDNODE_H + +#include "node/executionnode.h" +#include "result/diceresult.h" + +/** + * @brief The MergeNode class is an ExecutionNode. It is dedicated to merge result of several commands. + */ +class BindNode : public ExecutionNode +{ +public: + BindNode(); + void run(ExecutionNode* previous); + virtual QString toString(bool withLabel) const; + virtual qint64 getPriority() const; + virtual ExecutionNode* getCopy() const; + std::vector<ExecutionNode*>* getStartList() const; + void setStartList(std::vector<ExecutionNode*>* startList); + +private: + ExecutionNode* getLatestNode(ExecutionNode* node); + +private: + DiceResult* m_diceResult; + std::vector<ExecutionNode*>* m_startList; +}; + +#endif // NUMBERNODE_H diff --git a/src/libparser/node/countexecutenode.cpp b/src/libparser/node/countexecutenode.cpp new file mode 100644 index 0000000..b45fe37 --- /dev/null +++ b/src/libparser/node/countexecutenode.cpp @@ -0,0 +1,76 @@ +#include "countexecutenode.h" +#include "result/diceresult.h" +#include "validatorlist.h" + +CountExecuteNode::CountExecuteNode() : m_scalarResult(new ScalarResult()), m_validatorList(nullptr) +{ + m_result= m_scalarResult; +} +void CountExecuteNode::setValidatorList(ValidatorList* validatorlist) +{ + m_validatorList= validatorlist; +} +CountExecuteNode::~CountExecuteNode() +{ + if(nullptr != m_validatorList) + { + delete m_validatorList; + } +} + +void CountExecuteNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr == previous) + { + m_errors.insert(Dice::ERROR_CODE::NO_PREVIOUS_ERROR, QStringLiteral("No scalar result before Swith/Case operator")); + return; + } + DiceResult* previousResult= dynamic_cast<DiceResult*>(previous->getResult()); + if(nullptr != previousResult) + { + m_result->setPrevious(previousResult); + qint64 sum= 0; + std::function<void(Die*, qint64)> f= [&sum](const Die*, qint64 score) { sum+= score; }; + m_validatorList->validResult(previousResult, true, true, f); + m_scalarResult->setValue(sum); + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } + } +} +QString CountExecuteNode::toString(bool withlabel) const +{ + if(withlabel) + { + return QString("%1 [label=\"CountExecuteNode %2\"]").arg(m_id, m_validatorList->toString()); + } + else + { + return m_id; + } +} +qint64 CountExecuteNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_previousNode) + { + priority= m_previousNode->getPriority(); + } + return priority; +} + +ExecutionNode* CountExecuteNode::getCopy() const +{ + CountExecuteNode* node= new CountExecuteNode(); + if(nullptr != m_validatorList) + { + node->setValidatorList(m_validatorList->getCopy()); + } + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/countexecutenode.h b/src/libparser/node/countexecutenode.h new file mode 100644 index 0000000..37b7a4f --- /dev/null +++ b/src/libparser/node/countexecutenode.h @@ -0,0 +1,50 @@ +#ifndef COUNTEXECUTENODE_H +#define COUNTEXECUTENODE_H + +#include "executionnode.h" + +#include "result/scalarresult.h" + +class ValidatorList; +/** + * @brief The CountExecuteNode class + */ +class CountExecuteNode : public ExecutionNode +{ +public: + /** + * @brief CountExecuteNode + */ + CountExecuteNode(); + virtual ~CountExecuteNode(); + /** + * @brief run + * @param previous + */ + virtual void run(ExecutionNode* previous); + /** + * @brief setValidator + */ + virtual void setValidatorList(ValidatorList*); + /** + * @brief toString + * @return + */ + virtual QString toString(bool withLabel) const; + /** + * @brief getPriority + * @return + */ + virtual qint64 getPriority() const; + /** + * @brief getCopy + * @return + */ + virtual ExecutionNode* getCopy() const; + +private: + ScalarResult* m_scalarResult; + ValidatorList* m_validatorList; +}; + +#endif // COUNTEXECUTENODE_H diff --git a/src/libparser/node/dicerollernode.cpp b/src/libparser/node/dicerollernode.cpp new file mode 100644 index 0000000..2b00c0a --- /dev/null +++ b/src/libparser/node/dicerollernode.cpp @@ -0,0 +1,121 @@ +#include "dicerollernode.h" +#include "die.h" + +#include <QDebug> +#include <QThread> +#include <QThreadPool> +#include <QTime> + +DiceRollerNode::DiceRollerNode(qint64 max, qint64 min) + : m_max(max), m_diceResult(new DiceResult()), m_min(min), m_operator(Dice::ArithmeticOperator::PLUS) +{ + m_result= m_diceResult; +} +void DiceRollerNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr != previous) + { + Result* result= previous->getResult(); + if(nullptr != result) + { + auto num= result->getResult(Dice::RESULT_TYPE::SCALAR).toReal(); + if(num <= 0) + { + m_errors.insert(Dice::ERROR_CODE::NO_DICE_TO_ROLL, QObject::tr("No dice to roll")); + } + m_diceCount= num > 0 ? static_cast<quint64>(num) : 0; + m_result->setPrevious(result); + + auto possibleValue= static_cast<quint64>(std::abs((m_max - m_min) + 1)); + if(possibleValue < m_diceCount && m_unique) + { + m_errors.insert(Dice::ERROR_CODE::TOO_MANY_DICE, + QObject::tr("More unique values asked than possible values (D operator)")); + return; + } + + for(quint64 i= 0; i < m_diceCount; ++i) + { + Die* die= new Die(); + die->setOp(m_operator); + die->setBase(m_min); + die->setMaxValue(m_max); + die->roll(); + if(m_unique) + { + const auto& equal= [](const Die* a, const Die* b) { return a->getValue() == b->getValue(); }; + while(m_diceResult->contains(die, equal)) + { + die->roll(false); + } + } + m_diceResult->insertResult(die); + } + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } + } + } +} + +quint64 DiceRollerNode::getFaces() const +{ + return static_cast<quint64>(std::abs(m_max - m_min) + 1); +} + +std::pair<qint64, qint64> DiceRollerNode::getRange() const +{ + return std::make_pair(m_min, m_max); +} +QString DiceRollerNode::toString(bool wl) const +{ + if(wl) + { + return QString("%1 [label=\"DiceRollerNode faces: %2\"]").arg(m_id).arg(getFaces()); + } + else + { + return m_id; + } +} +qint64 DiceRollerNode::getPriority() const +{ + qint64 priority= 4; + // if(nullptr!=m_nextNode) + // { + // priority = m_nextNode->getPriority(); + // } + return priority; +} +ExecutionNode* DiceRollerNode::getCopy() const +{ + DiceRollerNode* node= new DiceRollerNode(m_max, m_min); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} + +Dice::ArithmeticOperator DiceRollerNode::getOperator() const +{ + return m_operator; +} + +void DiceRollerNode::setOperator(const Dice::ArithmeticOperator& dieOperator) +{ + m_operator= dieOperator; + m_diceResult->setOperator(dieOperator); +} + +bool DiceRollerNode::getUnique() const +{ + return m_unique; +} + +void DiceRollerNode::setUnique(bool unique) +{ + m_unique= unique; +} diff --git a/src/libparser/node/dicerollernode.h b/src/libparser/node/dicerollernode.h new file mode 100644 index 0000000..52178cb --- /dev/null +++ b/src/libparser/node/dicerollernode.h @@ -0,0 +1,63 @@ +#ifndef DICEROLLERNODE_H +#define DICEROLLERNODE_H + +#include <Qt> + +#include "executionnode.h" +#include "result/diceresult.h" +#include <utility> +/** + * @brief The DiceRollerNode class rolls dice of one kind. + */ +class DiceRollerNode : public ExecutionNode +{ +public: + /** + * @brief DiceRollerNode builds an instance + * @param faces, number of faces of dices + * @param offset, first value of dice. + */ + DiceRollerNode(qint64 max, qint64 min= 1); + + /** + * @brief run - starts to roll dice. + */ + virtual void run(ExecutionNode*); + /** + * @brief getFaces accessor + * @return the face count + */ + quint64 getFaces() const; + std::pair<qint64, qint64> getRange() const; + + /** + * @brief toString + * @param wl + * @return use to generate dot tree; + */ + virtual QString toString(bool wl) const; + /** + * @brief getPriority + * @return priority for dice roll: 4 (higher) + */ + virtual qint64 getPriority() const; + + virtual ExecutionNode* getCopy() const; + + // private members + Dice::ArithmeticOperator getOperator() const; + void setOperator(const Dice::ArithmeticOperator& dieOperator); + + bool getUnique() const; + void setUnique(bool unique); + +private: + quint64 m_diceCount; + qint64 m_max; /// faces + DiceResult* m_diceResult{nullptr}; + qint64 m_min; + Dice::ArithmeticOperator m_operator; + bool m_unique{false}; +}; + +#endif // DICEROLLERNODE_H diff --git a/src/libparser/node/executionnode.cpp b/src/libparser/node/executionnode.cpp new file mode 100644 index 0000000..4545934 --- /dev/null +++ b/src/libparser/node/executionnode.cpp @@ -0,0 +1,101 @@ +#include "executionnode.h" + +#include <QUuid> + +ExecutionNode::ExecutionNode() + : m_previousNode(nullptr) + , m_result(nullptr) + , m_nextNode(nullptr) + , m_errors(QMap<Dice::ERROR_CODE, QString>()) + , m_id(QString("\"%1\"").arg(QUuid::createUuid().toString())) +{ +} +ExecutionNode::~ExecutionNode() +{ + if(nullptr != m_result) + { + delete m_result; + m_result= nullptr; + } + if(nullptr != m_nextNode) + { + delete m_nextNode; + m_nextNode= nullptr; + } +} + +Result* ExecutionNode::getResult() +{ + return m_result; +} +void ExecutionNode::setNextNode(ExecutionNode* node) +{ + m_nextNode= node; +} +void ExecutionNode::setPreviousNode(ExecutionNode* node) +{ + m_previousNode= node; +} +ExecutionNode* ExecutionNode::getNextNode() +{ + return m_nextNode; +} +QMap<Dice::ERROR_CODE, QString> ExecutionNode::getExecutionErrorMap() +{ + if(nullptr != m_nextNode) + { + auto const& keys= m_nextNode->getExecutionErrorMap().keys(); + for(auto& key : keys) + { + m_errors.insert(key, m_nextNode->getExecutionErrorMap().value(key)); + } + } + return m_errors; +} +QString ExecutionNode::getHelp() +{ + return QString(); +} +ExecutionNode* ExecutionNode::getPreviousNode() const +{ + return m_previousNode; +} +void ExecutionNode::generateDotTree(QString& s) +{ + auto str= toString(true); + if(s.contains(str)) + return; + s.append(toString(true)); + s.append(";\n"); + + if(nullptr != m_nextNode) + { + s.append(toString(false)); + s.append(" -> "); + s.append(m_nextNode->toString(false)); + s.append("[label=\"next\"];\n"); + // s.append(" [label=\"nextNode\"];\n"); + m_nextNode->generateDotTree(s); + } + else + { + s.append(toString(false)); + s.append(" -> "); + s.append("nullptr;\n"); + } + if(nullptr != m_result) + { + s.append(toString(false)); + s.append(" ->"); + s.append(m_result->toString(false)); + s.append(" [label=\"Result\", style=\"dashed\"];\n"); + if(nullptr == m_nextNode) + m_result->generateDotTree(s); + } +} +qint64 ExecutionNode::getScalarResult() +{ + if(m_result == nullptr) + return 0; + return m_result->getResult(Dice::RESULT_TYPE::SCALAR).toInt(); +} diff --git a/src/libparser/node/executionnode.h b/src/libparser/node/executionnode.h new file mode 100644 index 0000000..d1bdf66 --- /dev/null +++ b/src/libparser/node/executionnode.h @@ -0,0 +1,102 @@ +#ifndef EXECUTIONNODE_H +#define EXECUTIONNODE_H + +#include "result/result.h" +#include <diceparser/diceparserhelper.h> + +/** + * @brief The ExecutionNode class + */ +class ExecutionNode +{ +public: + /** + * @brief ExecutionNode + */ + ExecutionNode(); + /** + * @brief ~ExecutionNode + */ + virtual ~ExecutionNode(); + /** + * @brief run + * @param previous + */ + virtual void run(ExecutionNode* previous= nullptr)= 0; + /** + * @brief getResult + * @return + */ + virtual Result* getResult(); + /** + * @brief setNextNode + */ + void setNextNode(ExecutionNode*); + /** + * @brief getNextNode + * @return + */ + ExecutionNode* getNextNode(); + /** + * @brief getPreviousNode + * @return + */ + virtual ExecutionNode* getPreviousNode() const; + void setPreviousNode(ExecutionNode* node); + /** + * @brief toString + * @return + */ + virtual QString toString(bool withLabel) const= 0; + /** + * @brief getPriority + * @return + */ + virtual qint64 getPriority() const= 0; + /** + * @brief getErrorList + * @return + */ + virtual QMap<Dice::ERROR_CODE, QString> getExecutionErrorMap(); + + /** + * @brief generateDotTree + */ + virtual void generateDotTree(QString&); + + /** + * @brief getHelp + * @return + */ + virtual QString getHelp(); + + /** + * @brief getCopy + * @return should return a copy of that node. + */ + virtual ExecutionNode* getCopy() const= 0; + + virtual qint64 getScalarResult(); + +protected: + /** + * @brief m_nextNode + */ + ExecutionNode* m_previousNode= nullptr; + /** + * @brief m_result + */ + Result* m_result= nullptr; + /** + * @brief m_nextNode + */ + ExecutionNode* m_nextNode= nullptr; + /** + * @brief m_errors + */ + QMap<Dice::ERROR_CODE, QString> m_errors; + + QString m_id; +}; + +#endif // EXECUTIONNODE_H diff --git a/src/libparser/node/explodedicenode.cpp b/src/libparser/node/explodedicenode.cpp new file mode 100644 index 0000000..1546883 --- /dev/null +++ b/src/libparser/node/explodedicenode.cpp @@ -0,0 +1,117 @@ +#include "explodedicenode.h" +#include "validatorlist.h" + +ExplodeDiceNode::ExplodeDiceNode() : m_diceResult(new DiceResult()) +{ + m_result= m_diceResult; +} +void ExplodeDiceNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if((nullptr != previous) && (nullptr != previous->getResult())) + { + DiceResult* previous_result= dynamic_cast<DiceResult*>(previous->getResult()); + m_result->setPrevious(previous_result); + if(nullptr != previous_result) + { + Die* exampleDie; + for(auto& die : previous_result->getResultList()) + { + Die* tmpdie= new Die(*die); + m_diceResult->insertResult(tmpdie); + die->displayed(); + exampleDie= tmpdie; + } + + // QList<Die*> list= m_diceResult->getResultList(); + + bool hasExploded= false; + std::function<void(Die*, qint64)> f= [&hasExploded, this](Die* die, qint64) { + if(Dice::CONDITION_STATE::ALWAYSTRUE + == m_validatorList->isValidRangeSize( + std::make_pair<qint64, qint64>(die->getBase(), die->getMaxValue()))) + { + m_errors.insert(Dice::ERROR_CODE::ENDLESS_LOOP_ERROR, + QObject::tr("Condition (%1) cause an endless loop with this dice: %2") + .arg(toString(true)) + .arg(QStringLiteral("d[%1,%2]") + .arg(static_cast<int>(die->getBase())) + .arg(static_cast<int>(die->getMaxValue())))); + } + hasExploded= true; + die->roll(true); + }; + do + { + hasExploded= false; + m_validatorList->validResult(m_diceResult, false, false, f); + } while(hasExploded); + + /*for(auto& die : list) + { + if(Dice::CONDITION_STATE::ALWAYSTRUE + == m_validatorList->isValidRangeSize( + std::make_pair<qint64, qint64>(die->getBase(), die->getMaxValue()))) + { + + continue; + } + + while(m_validatorList->hasValid(die, false)) + { + die->roll(true); + } + }*/ + + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } + } + } +} +ExplodeDiceNode::~ExplodeDiceNode() +{ + if(nullptr != m_validatorList) + { + delete m_validatorList; + } +} +void ExplodeDiceNode::setValidatorList(ValidatorList* val) +{ + m_validatorList= val; +} +QString ExplodeDiceNode::toString(bool withlabel) const +{ + if(withlabel) + { + return QString("%1 [label=\"ExplodeDiceNode %2\"]").arg(m_id, m_validatorList->toString()); + } + else + { + return m_id; + } +} +qint64 ExplodeDiceNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_previousNode) + { + priority= m_previousNode->getPriority(); + } + return priority; +} + +ExecutionNode* ExplodeDiceNode::getCopy() const +{ + ExplodeDiceNode* node= new ExplodeDiceNode(); + if(nullptr != m_validatorList) + { + node->setValidatorList(m_validatorList->getCopy()); + } + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/explodedicenode.h b/src/libparser/node/explodedicenode.h new file mode 100644 index 0000000..77b4a44 --- /dev/null +++ b/src/libparser/node/explodedicenode.h @@ -0,0 +1,29 @@ +#ifndef EXPLOSEDICENODE_H +#define EXPLOSEDICENODE_H + +#include "executionnode.h" +#include "result/diceresult.h" + +class ValidatorList; + +/** + * @brief The ExplodeDiceNode class explode dice while is valid by the validator. + */ +class ExplodeDiceNode : public ExecutionNode +{ +public: + ExplodeDiceNode(); + virtual ~ExplodeDiceNode(); + virtual void run(ExecutionNode* previous= nullptr); + virtual void setValidatorList(ValidatorList*); + virtual QString toString(bool) const; + virtual qint64 getPriority() const; + + virtual ExecutionNode* getCopy() const; + +protected: + DiceResult* m_diceResult; + ValidatorList* m_validatorList= nullptr; +}; + +#endif // EXPLOSEDICENODE_H diff --git a/src/libparser/node/filternode.cpp b/src/libparser/node/filternode.cpp new file mode 100644 index 0000000..b72b6e1 --- /dev/null +++ b/src/libparser/node/filternode.cpp @@ -0,0 +1,94 @@ +#include "filternode.h" +#include "validatorlist.h" + +FilterNode::FilterNode() : m_diceResult(new DiceResult()), m_eachValue(false) +{ + m_result= m_diceResult; +} + +FilterNode::~FilterNode() +{ + if(nullptr != m_validatorList) + { + delete m_validatorList; + } +} +void FilterNode::setValidatorList(ValidatorList* validatorlist) +{ + m_validatorList= validatorlist; +} +void FilterNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr == previous) + { + return; + } + DiceResult* previousDiceResult= dynamic_cast<DiceResult*>(previous->getResult()); + m_result->setPrevious(previousDiceResult); + + if(nullptr != previousDiceResult) + { + QList<Die*> diceList2; + std::function<void(Die*, qint64)> f= [&diceList2](Die* die, qint64) { + if(die == nullptr) + return; + Die* tmpdie= new Die(*die); + diceList2.append(tmpdie); + die->displayed(); + }; + m_validatorList->validResult(previousDiceResult, true, true, f); + + QList<Die*> diceList= previousDiceResult->getResultList(); + + diceList.erase(std::remove_if(diceList.begin(), diceList.end(), + [&diceList2](Die* die) { return diceList2.contains(die); }), + diceList.end()); + for(Die* tmp : diceList) + { + tmp->setHighlighted(false); + tmp->setDisplayed(true); + } + + m_diceResult->setResultList(diceList2); + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } + } +} + +QString FilterNode::toString(bool wl) const +{ + if(wl) + { + return QString("%1 [label=\"FilterNode\"]").arg(m_id); + } + else + { + return m_id; + } +} +qint64 FilterNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_nextNode) + { + priority= m_nextNode->getPriority(); + } + + return priority; +} +ExecutionNode* FilterNode::getCopy() const +{ + FilterNode* node= new FilterNode(); + if(nullptr != m_validatorList) + { + node->setValidatorList(m_validatorList->getCopy()); + } + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/filternode.h b/src/libparser/node/filternode.h new file mode 100644 index 0000000..7af6fe2 --- /dev/null +++ b/src/libparser/node/filternode.h @@ -0,0 +1,40 @@ +#ifndef FILTERNODE_H +#define FILTERNODE_H + +#include "executionnode.h" + +#include "result/diceresult.h" + +class ValidatorList; + +class FilterNode : public ExecutionNode +{ +public: + FilterNode(); + virtual ~FilterNode(); + + virtual void run(ExecutionNode* previous); + /** + * @brief setValidator + */ + virtual void setValidatorList(ValidatorList*); + /** + * @brief toString + * @return + */ + virtual QString toString(bool withLabel) const; + /** + * @brief getPriority + * @return + */ + virtual qint64 getPriority() const; + + virtual ExecutionNode* getCopy() const; + +private: + DiceResult* m_diceResult; + ValidatorList* m_validatorList; + bool m_eachValue; +}; + +#endif // FILTERNODE_H diff --git a/src/libparser/node/forloopnode.cpp b/src/libparser/node/forloopnode.cpp new file mode 100644 index 0000000..aba6ff4 --- /dev/null +++ b/src/libparser/node/forloopnode.cpp @@ -0,0 +1,103 @@ +#include "forloopnode.h" + +#include "die.h" + +MockNode::MockNode() {} + +void MockNode::run(ExecutionNode* node) +{ + return; +} + +void MockNode::setResult(Result* result) +{ + m_result= result; +} + +QString MockNode::toString(bool) const +{ + return {}; +}; +qint64 MockNode::getPriority() const +{ + return 0; +} +ExecutionNode* MockNode::getCopy() const +{ + return new MockNode(); +} +// end mocknode + +ForLoopNode::ForLoopNode() : m_diceResult(new DiceResult) {} + +void ForLoopNode::setInternal(ExecutionNode* node) +{ + m_internal.reset(node); +} + +void ForLoopNode::run(ExecutionNode* previous) +{ + if(nullptr != previous) + { + auto prevResult= dynamic_cast<DiceResult*>(previous->getResult()); + if(nullptr != prevResult) + { + m_diceResult->setPrevious(prevResult); + QList<Die*> diceList= prevResult->getResultList(); + for(Die* dice : diceList) + { + MockNode node; + DiceResult diceResult; + diceResult.insertResult(dice); + node.setResult(&diceResult); + m_internal->run(&node); + + auto tmp= m_internal.get(); + while(nullptr != tmp->getNextNode()) + { + tmp= tmp->getNextNode(); + } + Result* internalResult= tmp->getResult(); + auto value= internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toInt(); + + Die* neodie= new Die(); + *neodie= *dice; + neodie->setValue(value); + m_diceResult->insertResult(neodie); + node.setResult(nullptr); + diceResult.clear(); + dice->displayed(); + } + } + } + m_result= m_diceResult; + if(m_nextNode != nullptr) + m_nextNode->run(this); +} + +qint64 ForLoopNode::getPriority() const +{ + return 2; +} + +QString ForLoopNode::toString(bool withLabel) const +{ + if(withLabel) + { + return QString("%1 [label=\"ForLoopNode Node\"]").arg(m_id); + } + else + { + return m_id; + } +} + +ExecutionNode* ForLoopNode::getCopy() const +{ + auto node= new ForLoopNode(); + if(m_internal) + { + node->setInternal(m_internal->getCopy()); + } + return node; +} diff --git a/src/libparser/node/forloopnode.h b/src/libparser/node/forloopnode.h new file mode 100644 index 0000000..a9acf20 --- /dev/null +++ b/src/libparser/node/forloopnode.h @@ -0,0 +1,36 @@ +#ifndef FORLOOPNODE_H +#define FORLOOPNODE_H + +#include "executionnode.h" +#include "result/diceresult.h" +#include <memory> + +class MockNode : public ExecutionNode +{ +public: + MockNode(); + void run(ExecutionNode* node); + void setResult(Result* result); + QString toString(bool withLabel) const; + qint64 getPriority() const; + ExecutionNode* getCopy() const; +}; + +class ForLoopNode : public ExecutionNode +{ +public: + ForLoopNode(); + void run(ExecutionNode* previous); + + void setInternal(ExecutionNode* internal); + + QString toString(bool withLabel) const; + qint64 getPriority() const; + ExecutionNode* getCopy() const; + +private: + std::unique_ptr<ExecutionNode> m_internal; + DiceResult* m_diceResult; +}; + +#endif // FORLOOPNODE_H diff --git a/src/libparser/node/groupnode.cpp b/src/libparser/node/groupnode.cpp new file mode 100644 index 0000000..860d758 --- /dev/null +++ b/src/libparser/node/groupnode.cpp @@ -0,0 +1,312 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "groupnode.h" +#include "result/diceresult.h" +//------------------------------- +int DieGroup::getSum() const +{ + int sum= 0; + for(int i : *this) + { + sum+= i; + } + return sum; +} + +void DieGroup::removeValue(DieGroup i) +{ + for(auto x : i) + { + removeOne(x); + } +} + +int DieGroup::getLost() const +{ + return getSum() - m_exceptedValue; +} + +qint64 DieGroup::getExceptedValue() const +{ + return m_exceptedValue; +} + +void DieGroup::setExceptedValue(qint64 exceptedValue) +{ + m_exceptedValue= exceptedValue; +} + +//--------------------- +GroupNode::GroupNode(bool complexOutput) + : m_scalarResult(new ScalarResult), m_stringResult(new StringResult), m_complexOutput(complexOutput) +{ +} + +void GroupNode::run(ExecutionNode* previous) +{ + if(m_complexOutput) + m_result= m_stringResult; + else + m_result= m_scalarResult; + + m_previousNode= previous; + if(nullptr != previous) + { + m_result->setPrevious(previous->getResult()); + Result* tmpResult= previous->getResult(); + if(nullptr != tmpResult) + { + DiceResult* dice= dynamic_cast<DiceResult*>(tmpResult); + if(nullptr != dice) + { + auto list= dice->getResultList(); + DieGroup allResult; + for(auto& die : list) + { + allResult << die->getListValue(); + } + std::sort(allResult.begin(), allResult.end(), std::greater<qint64>()); + if(allResult.getSum() > m_groupValue) + { + auto copy= allResult; + auto const die= getGroup(allResult); + + for(auto list : die) + { + for(auto val : list) + { + copy.removeOne(val); + } + } + m_scalarResult->setValue(die.size()); + QStringList list; + for(auto group : die) + { + QStringList values; + std::transform(group.begin(), group.end(), std::back_inserter(values), + [](qint64 val) { return QString::number(val); }); + list << QStringLiteral("{%1}").arg(values.join(",")); + } + QStringList unused; + std::transform(copy.begin(), copy.end(), std::back_inserter(unused), + [](qint64 val) { return QString::number(val); }); + if(!unused.isEmpty()) + m_stringResult->addText( + QStringLiteral("%1 (%2 - [%3])").arg(die.size()).arg(list.join(",")).arg(unused.join(","))); + else + m_stringResult->addText(QStringLiteral("%1 (%2)").arg(die.size()).arg(list.join(","))); + } + else + { + m_scalarResult->setValue(0); + } + } + } + } + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} + +QString GroupNode::toString(bool withLabel) const +{ + if(withLabel) + { + return QString("%1 [label=\"SplitNode Node\"]").arg(m_id); + } + else + { + return m_id; + } +} +qint64 GroupNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_nextNode) + { + priority= m_nextNode->getPriority(); + } + return priority; +} +ExecutionNode* GroupNode::getCopy() const +{ + GroupNode* node= new GroupNode(m_complexOutput); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} + +int GroupNode::getGroupValue() const +{ + return m_groupValue; +} + +void GroupNode::setGroupValue(qint64 groupValue) +{ + m_groupValue= groupValue; +} + +bool GroupNode::composeWithPrevious(DieGroup previous, qint64 first, qint64 current, DieGroup& addValue) +{ + if(previous.getSum() + first + current == m_groupValue) + { + addValue.append(previous); + addValue.append(first); + addValue.append(current); + return true; + } + + if(previous.isEmpty()) + return false; + + int maxComboLength= previous.size(); + bool hasReachMax= false; + + QList<DieGroup> possibleUnion; + for(auto va : previous) + { + DieGroup dieG; + dieG.append(va); + possibleUnion.append(dieG); + } + + while(!hasReachMax) + { + auto tmpValues= previous; + QList<DieGroup> possibleTmp; + for(auto& diaG : possibleUnion) + { + if(tmpValues.isEmpty()) + break; + tmpValues.removeValue(diaG); + + for(auto& value : tmpValues) + { + DieGroup dia; + dia.append(diaG); + dia.append(value); + if(dia.size() >= maxComboLength - 1) + hasReachMax= true; + else + possibleTmp.append(dia); + } + } + if(possibleTmp.isEmpty()) + hasReachMax= true; + else + { + possibleTmp.append(possibleUnion); + possibleUnion= possibleTmp; + } + } + std::sort(possibleUnion.begin(), possibleUnion.end(), + [=](const DieGroup& a, const DieGroup& b) { return a.getLost() > b.getLost(); }); + bool found= false; + for(int i= 0; (!found && i < possibleUnion.size()); ++i) + { + auto& value= possibleUnion.at(i); + if(value.getSum() + current + first >= m_groupValue) + { + addValue << value << current << first; + found= true; + } + } + return found; +} + +QList<DieGroup> GroupNode::getGroup(DieGroup values) +{ + if(values.isEmpty()) + return {}; + + auto first= values.takeFirst(); + + QList<DieGroup> result; + QMap<qint64, DieGroup> loseMap; + if(first >= m_groupValue) + { + DieGroup group; + group << first; + loseMap[0]= group; + } + else + { + auto it= values.rbegin(); + bool foundPerfect= false; + qint64 cumuledValue= 0; + DieGroup previousValue; + while((values.rend() != it) && !foundPerfect) + { + if(first + *it == m_groupValue) + { + foundPerfect= true; + DieGroup group; + group << first << *it; + loseMap[0]= group; + } + else if(first + *it > m_groupValue) + { + DieGroup group; + group << first << *it; + loseMap[first + *it - m_groupValue]= group; + } + else if(first + *it + cumuledValue == m_groupValue) + { + DieGroup group; + group << first << *it << previousValue; + foundPerfect= true; + loseMap[0]= group; + } + else if(first + *it + cumuledValue > m_groupValue) + { + DieGroup group; + group.setExceptedValue(m_groupValue); + auto b= composeWithPrevious(previousValue, first, *it, group); + if(b) + loseMap[group.getLost()]= group; + } + previousValue << *it; + cumuledValue+= *it; + ++it; + } + } + if(!loseMap.isEmpty()) + { + DieGroup die= loseMap.first(); + result.append(die); + DieGroup valueToRemove= die; + if(!valueToRemove.isEmpty()) + { + valueToRemove.removeFirst(); + values.removeValue(valueToRemove); + + if(values.getSum() >= m_groupValue) + { + result.append(getGroup(values)); + } + } + } + return result; +} diff --git a/src/libparser/node/groupnode.h b/src/libparser/node/groupnode.h new file mode 100644 index 0000000..d037080 --- /dev/null +++ b/src/libparser/node/groupnode.h @@ -0,0 +1,72 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef GROUPNODE_H +#define GROUPNODE_H + +#include "node/executionnode.h" +#include "result/scalarresult.h" +#include "result/stringresult.h" +#include <QList> + +class DieGroup : public QList<qint64> +{ +public: + int getSum() const; + void removeValue(DieGroup); + + int getLost() const; + + qint64 getExceptedValue() const; + void setExceptedValue(qint64 exceptedValue); + +private: + qint64 m_exceptedValue= 0; +}; +/** + * @brief The GroupNode class is an ExecutionNode. + */ +class GroupNode : public ExecutionNode +{ +public: + GroupNode(bool complexOutput= false); + void run(ExecutionNode* previous) override; + virtual QString toString(bool withLabel) const override; + virtual qint64 getPriority() const override; + virtual ExecutionNode* getCopy() const override; + + int getGroupValue() const; + void setGroupValue(qint64 groupValue); + + QList<DieGroup> getGroup(DieGroup); + +protected: + bool composeWithPrevious(DieGroup previous, qint64 first, qint64 current, DieGroup& addValue); + +private: + ScalarResult* m_scalarResult; + StringResult* m_stringResult; + qint64 m_groupValue; + QList<DieGroup> m_groupsList; + bool m_complexOutput= false; +}; + +#endif // GROUPNODE_H diff --git a/src/libparser/node/helpnode.cpp b/src/libparser/node/helpnode.cpp new file mode 100644 index 0000000..8ab48a9 --- /dev/null +++ b/src/libparser/node/helpnode.cpp @@ -0,0 +1,142 @@ +/*************************************************************************** + * Copyright (C) 2015 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "helpnode.h" + +HelpNode::HelpNode() : m_path("https://github.com/Rolisteam/DiceParser/blob/master/HelpMe.md") +{ + m_result= new StringResult(); +} +void HelpNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + StringResult* txtResult= dynamic_cast<StringResult*>(m_result); + txtResult->setHighLight(false); + + if((nullptr == previous) && (txtResult != nullptr)) + { + txtResult->addText(QObject::tr("Rolisteam Dice Parser:\n" + "\n" + "Example (with ! as prefix):\n" + "!2d6\n" + "!1d20\n" + "!6d10e10k3 (L5R)\n" + "\n" + "Full documentation at: %1") + .arg(m_path)); + /*txtResult->setText(QObject::tr("Rolisteam Dice Parser:\n" + "\n" + "Example (with ! as prefix):\n" + "!2d6\n" + "!1d20\n" + "\n" + "Operator list:\n" + "\n" + "k : Keep : 2d10k1 => roll two 10-sided dice and keep the + higher one (kl1 for smaller one)\n" "K : Keep And Explode : 2d10K1 => Equivalent of 2d10e10k1\n" "s : + Sort : 8d10 => roll eight 10-sided dice and sort the result list\n" "c : Count : + 8d10c[>7] => roll eight 10-sided dice and count how many dice are higher than 7\n" "r : Reroll : + 8d6r1 => roll eight 6-sided dice and reroll dice once if its result is 1. (result of the reroll can be + 1)\n" "e : Explode : 8d10e10 => roll eight 10-sided dice and while dice makes a 10 it is + reroll. The result is added to those dice.\n" "a : Reroll and add : 8d6a1 => roll eight 6-sided dice + and reroll dice once and the result is added at 1\n" "m : Merge : 1d20;1d10mk1 => roll one 20-side + die and one 10-sided die and keep the higher die\n" "i : if : 1d100i[=100]{\"jackpot\"} => Roll + one 100-side die and display \"jackpot\" if the die result is 100.\n" "f : filter : 4d10f[!=4] => + roll four 10-sided dice and ignore all dice with 4 as result" + "; : Next instruction : 1d20;2d10;3d8 => roll one 20-sided die, two 10-sided + dice and three 8-sided dice \n" "g : Group : 8d10g10 => count how many group of 10 it is + possible to do (according to rule of 7th sea).\n" + "# : Comment : 1d2 #flip coin=> display flip coin as comment of 1 or 2 + result.\n" + "\n" + "Validator:\n" + "\n" + "Supported conditions: >,<,=,>=,<=,!=\n" + "Supported operators: % (modulo), &,^,| \n" + "\n" + " Examples:\n" + "\n" + "c[>7 & %2=0] : count how many dice are higher than 7 and even\n" + "c[>7 | %2=0] : count how many dice are higher than 7 or even\n" + "c[>7 ^ %2=0] : count how many dice are higher than 7 or even but not higher + than 7 and even\n" + "\n" + "List:\n" + "\n" + "1L[green,blue] => pick value from the list (green or blue)\n" + "2L[green,blue] => pick two values from the list (green,green | green,blue | + blue,green | blue,blue)\n" "2Lu[green,blue] => pick two unique values from the list (green,blue | + blue,green)\n" + "\n" + "Arithmetic\n" + "\n" + "8+8+8 => 24\n" + "24-4 => 20\n" + "(3+4)*2 => 14\n" + "7/2 => 3.5\n" + "2^4 => 16\n" + "1d6+6 => roll one 6-sided die and add 6 to its result\n" + "(2d4+2)d10 => roll two 4-sided dice, add 2 to the result[2;8] then roll from + four to ten 10-sided dice\n" + "\n" + "Full documentation at: %1").arg(m_path));*/ + m_result->setPrevious(nullptr); + } + else if(nullptr != previous) + { + txtResult->addText(previous->getHelp()); + m_result->setPrevious(previous->getResult()); + } + txtResult->finished(); + + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} +QString HelpNode::toString(bool wl) const +{ + if(wl) + { + return QString("%1 [label=\"Rolisteam Dice Parser:\nFull documentation at: %2\"]").arg(m_id, m_path); + } + else + { + return m_id; + } +} + +qint64 HelpNode::getPriority() const +{ + return 0; +} +void HelpNode::setHelpPath(QString path) +{ + m_path= path; +} + +ExecutionNode* HelpNode::getCopy() const +{ + HelpNode* node= new HelpNode(); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/helpnode.h b/src/libparser/node/helpnode.h new file mode 100644 index 0000000..a333c6d --- /dev/null +++ b/src/libparser/node/helpnode.h @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2015 by Renaud Guezennec * + * http:://www.rolisteam.org/contact * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef HELPNODE_H +#define HELPNODE_H +#include "executionnode.h" + +#include <QObject> +#include <QString> + +#include "result/stringresult.h" + +/** + * @brief The HelpNode class + */ +class HelpNode : public ExecutionNode +{ +public: + /** + * @brief HelpNode + */ + HelpNode(); + /** + * @brief run + * @param previous + */ + void run(ExecutionNode* previous); + /** + * @brief toString + * @return + */ + virtual QString toString(bool) const; + /** + * @brief getPriority + * @return + */ + virtual qint64 getPriority() const; + /** + * @brief setHelpPath + * @param path + */ + void setHelpPath(QString path); + /** + * @brief getCopy + * @return + */ + virtual ExecutionNode* getCopy() const; + +private: + QString m_path; +}; + +#endif // HELPNODE_H diff --git a/src/libparser/node/ifnode.cpp b/src/libparser/node/ifnode.cpp new file mode 100644 index 0000000..8de3cd5 --- /dev/null +++ b/src/libparser/node/ifnode.cpp @@ -0,0 +1,354 @@ +/*************************************************************************** + * Copyright (C) 2016 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "ifnode.h" +#include "result/diceresult.h" +#include "validatorlist.h" + +PartialDiceRollNode::PartialDiceRollNode() : m_diceResult(new DiceResult) +{ + m_result= m_diceResult; +} + +void PartialDiceRollNode::insertDie(Die* die) +{ + m_diceResult->insertResult(die); +} + +void PartialDiceRollNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + Result* presult= previous->getResult(); + if(nullptr != presult) + { + m_result->setPrevious(presult); + } + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} +ExecutionNode* PartialDiceRollNode::getCopy() const +{ + return new PartialDiceRollNode(); +} +qint64 PartialDiceRollNode::getPriority() const +{ + qint64 priority= 4; + return priority; +} + +QString PartialDiceRollNode::toString(bool withLabel) const +{ + if(withLabel) + { + return QString("%1 [label=\"PartialDiceRollNode \"]").arg(m_id); + } + else + { + return m_id; + } +} + +DiceResult* getFirstDiceResult(Result* result) +{ + DiceResult* found= nullptr; + + if(nullptr == result) + return found; + do + { + found= dynamic_cast<DiceResult*>(result); + result= result->getPrevious(); + } while((nullptr == found) && (result != nullptr)); + + return found; +} + +IfNode::IfNode() : m_conditionType(Dice::AllOfThem), m_true(nullptr), m_false(nullptr) +{ + // m_result = new DiceResult(); +} + +IfNode::~IfNode() +{ + m_result= nullptr; +} + +void IfNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr == previous) + { + return; + } + ExecutionNode* previousLoop= previous; + ExecutionNode* nextNode= nullptr; + bool runNext= (nullptr == m_nextNode) ? false : true; + Result* previousResult= previous->getResult(); + m_result= previousResult->getCopy(); + + if(nullptr != m_result) + { + qreal value= previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(); + + if(nullptr != m_validatorList) + { + DiceResult* previousDiceResult= getFirstDiceResult(previousResult); + if(nullptr != previousDiceResult) + { + QList<Die*> diceList= previousDiceResult->getResultList(); + + if(m_conditionType == Dice::OnEach) + { + for(Die* dice : diceList) + { + auto diceNode= new PartialDiceRollNode(); + diceNode->insertDie(new Die(*dice)); + if(m_validatorList->hasValid(dice, true, true)) + { + nextNode= (nullptr == m_true) ? nullptr : m_true->getCopy(); + } + else + { + nextNode= (nullptr == m_false) ? nullptr : m_false->getCopy(); + } + + if(nullptr != nextNode) + { + if(nullptr == previousLoop->getNextNode()) + { + previousLoop->setNextNode(nextNode); + } + if(nullptr == m_nextNode) + { + m_nextNode= nextNode; + } + diceNode->setNextNode(nextNode); + diceNode->run(previousLoop); + previousLoop= getLeafNode(nextNode); + } + } + } + else if((m_conditionType == Dice::OneOfThem) || (m_conditionType == Dice::AllOfThem)) + { + bool trueForAll= true; + bool falseForAll= true; + + bool oneIsTrue= false; + bool oneIsFalse= false; + + for(Die* dice : diceList) + { + bool result= m_validatorList->hasValid(dice, true, true); + trueForAll= trueForAll ? result : false; + falseForAll= falseForAll ? result : false; + + oneIsTrue|= result; + oneIsFalse= !result ? true : oneIsFalse; + } + if(m_conditionType == Dice::OneOfThem) + { + if(oneIsTrue) + { + nextNode= (nullptr == m_true) ? nullptr : m_true->getCopy(); + } + else // if(oneIsFalse) + { + nextNode= (nullptr == m_false) ? nullptr : m_false->getCopy(); + } + } + else if(m_conditionType == Dice::AllOfThem) + { + if(trueForAll) + { + nextNode= (nullptr == m_true) ? nullptr : m_true->getCopy(); + } + else // if(falseForAll) + { + nextNode= (nullptr == m_false) ? nullptr : m_false->getCopy(); + } + } + + if(nullptr != nextNode) + { + if(nullptr == m_nextNode) + { + m_nextNode= nextNode; + } + nextNode->run(previousLoop); + previousLoop= getLeafNode(nextNode); + } + } + } + + if(m_conditionType == Dice::OnScalar) + { + Die dice; + auto val= static_cast<qint64>(value); + dice.setValue(val); + dice.insertRollValue(val); + dice.setMaxValue(val); + if(m_validatorList->hasValid(&dice, true, true)) + { + nextNode= m_true; + } + else + { + nextNode= m_false; + } + if(nullptr != nextNode) + { + if(nullptr == m_nextNode) + { + m_nextNode= nextNode; + } + nextNode->run(previousLoop); + previousLoop= getLeafNode(nextNode); + } + } + } + } + + if((nullptr != m_nextNode) && (runNext)) + { + m_nextNode->run(previousLoop); + } +} + +void IfNode::setValidatorList(ValidatorList* val) +{ + m_validatorList= val; +} +void IfNode::setInstructionTrue(ExecutionNode* node) +{ + m_true= node; +} + +void IfNode::setInstructionFalse(ExecutionNode* node) +{ + m_false= node; +} +void IfNode::generateDotTree(QString& s) +{ + s.append(toString(true)); + s.append(";\n"); + + if((nullptr != m_true) && (m_true != m_nextNode)) + { + s.append(toString(false)); + s.append(" -> "); + s.append(m_true->toString(false)); + s.append("[label=\"true" + m_validatorList->toString() + "\"];\n"); + + m_true->generateDotTree(s); + } + if((nullptr != m_false) && (m_false != m_nextNode)) + { + s.append(toString(false)); + s.append(" -> "); + s.append(m_false->toString(false)); + s.append("[label=\"false\"];\n"); + m_false->generateDotTree(s); + } + + if(nullptr != m_nextNode) + { + s.append(toString(false)); + s.append(" -> "); + s.append(m_nextNode->toString(false)); + s.append("[label=\"next\"];\n"); + m_nextNode->generateDotTree(s); + } + else + { + s.append(toString(false)); + s.append(" -> "); + s.append("nullptr;\n"); + + if(nullptr != m_result) + { + s.append(toString(false)); + s.append(" ->"); + s.append(m_result->toString(false)); + s.append(" [label=\"Result\"];\n"); + m_result->generateDotTree(s); + } + } +} + +QString IfNode::toString(bool wl) const +{ + if(wl) + { + return QString("%1 [label=\"IfNode\"]").arg(m_id); + } + else + { + return m_id; + } +} + +qint64 IfNode::getPriority() const +{ + return 0; +} + +ExecutionNode* IfNode::getLeafNode(ExecutionNode* node) +{ + ExecutionNode* next= node; + while(nullptr != next->getNextNode()) + { + next= next->getNextNode(); + } + return next; +} + +Dice::ConditionType IfNode::getConditionType() const +{ + return m_conditionType; +} + +void IfNode::setConditionType(const Dice::ConditionType& conditionType) +{ + m_conditionType= conditionType; +} +ExecutionNode* IfNode::getCopy() const +{ + IfNode* node= new IfNode(); + + node->setConditionType(m_conditionType); + if(nullptr != m_validatorList) + { + node->setValidatorList(m_validatorList->getCopy()); + } + if(nullptr != m_false) + { + node->setInstructionFalse(m_false->getCopy()); + } + if(nullptr != m_true) + { + node->setInstructionTrue(m_true->getCopy()); + } + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/ifnode.h b/src/libparser/node/ifnode.h new file mode 100644 index 0000000..912d65c --- /dev/null +++ b/src/libparser/node/ifnode.h @@ -0,0 +1,117 @@ +/*************************************************************************** + * Copyright (C) 2015 by Renaud Guezennec * + * http:://www.rolisteam.org/contact * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef IFNODE_H +#define IFNODE_H + +#include "executionnode.h" +#include "result/diceresult.h" +#include <diceparser/diceparserhelper.h> + +class ValidatorList; +class PartialDiceRollNode : public ExecutionNode +{ +public: + PartialDiceRollNode(); + + void insertDie(Die* die); + virtual void run(ExecutionNode* previous= nullptr) override; + virtual qint64 getPriority() const override; + virtual ExecutionNode* getCopy() const override; + virtual QString toString(bool withLabel) const override; + +private: + DiceResult* m_diceResult; +}; + +/** + * @brief The ifNode class explode dice while is valid by the validator. + */ +class IfNode : public ExecutionNode +{ +public: + /** + * @brief IfNode + */ + IfNode(); + /** + * @brief ~IfNode + */ + virtual ~IfNode(); + /** + * @brief run + * @param previous + */ + virtual void run(ExecutionNode* previous= nullptr); + /** + * @brief setValidator + */ + virtual void setValidatorList(ValidatorList*); + /** + * @brief setInstructionTrue + */ + virtual void setInstructionTrue(ExecutionNode*); + /** + * @brief setInstructionFalse + */ + virtual void setInstructionFalse(ExecutionNode*); + /** + * @brief toString + * @return + */ + virtual QString toString(bool) const; + /** + * @brief getPriority + * @return + */ + virtual qint64 getPriority() const; + + /** + * @brief generateDotTree + */ + virtual void generateDotTree(QString&); + + /** + * @brief getCopy + * @return + */ + virtual ExecutionNode* getCopy() const; + /** + * @brief getConditionType + * @return + */ + Dice::ConditionType getConditionType() const; + + /** + * @brief setConditionType + * @param conditionType + */ + void setConditionType(const Dice::ConditionType& conditionType); + +protected: + ExecutionNode* getLeafNode(ExecutionNode* node); + +protected: + ValidatorList* m_validatorList= nullptr; + Dice::ConditionType m_conditionType; + + ExecutionNode* m_true; + ExecutionNode* m_false; +}; +#endif diff --git a/src/libparser/node/jumpbackwardnode.cpp b/src/libparser/node/jumpbackwardnode.cpp new file mode 100644 index 0000000..9fa0f45 --- /dev/null +++ b/src/libparser/node/jumpbackwardnode.cpp @@ -0,0 +1,168 @@ +/************************************************************************* + * Copyright (C) 2009 by Renaud Guezennec * + * * + * https://rolisteam.org/ * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published * + * by the Free Software Foundation; either version 2 of the License, * + * or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + *************************************************************************/ +#include "jumpbackwardnode.h" +#include <QDebug> + +JumpBackwardNode::JumpBackwardNode() +{ + m_previousNode= nullptr; + m_backwardNode= nullptr; + m_diceResult= new DiceResult(); + m_result= m_diceResult; +} + +qint64 JumpBackwardNode::getPriority() const +{ + return 4; +} +QString JumpBackwardNode::toString(bool wl) const +{ + if(wl) + { + return QString("%1 [label=\"JumpBackwardNode\"]").arg(m_id); + } + else + { + return m_id; + } +} +void JumpBackwardNode::generateDotTree(QString& s) +{ + s.append(toString(true)); + s.append(";\n"); + + if(nullptr != m_backwardNode) + { + s.append(toString(false)); + s.append(" -> "); + s.append(m_backwardNode->toString(false)); + s.append("[label=\"backward\"];\n"); + // m_backwardNode->generateDotTree(s); + } + + if(nullptr != m_nextNode) + { + s.append(toString(false)); + s.append(" -> "); + s.append(m_nextNode->toString(false)); + s.append("[label=\"next\"];\n"); + m_nextNode->generateDotTree(s); + } + else + { + s.append(toString(false)); + s.append(" -> "); + s.append("nullptr;\n"); + + if(nullptr != m_result) + { + s.append(toString(false)); + s.append(" ->"); + s.append(m_result->toString(false)); + s.append(" [label=\"Result\"];\n"); + m_result->generateDotTree(s); + } + } +} + +void JumpBackwardNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + ExecutionNode* parent= previous; + bool found= false; + // int i = 3; + Result* result= nullptr; + while((nullptr != parent) && (!found)) + { + result= parent->getResult(); + if(nullptr != result) + { + //--i; + if(/*(i==0)&&*/ (result->hasResultOfType(Dice::RESULT_TYPE::DICE_LIST))) + { + found= true; + m_backwardNode= parent; + } + else + { + JumpBackwardNode* jpNode= dynamic_cast<JumpBackwardNode*>(parent); + if(nullptr != jpNode) + { + found= true; + m_backwardNode= parent; + } + } + } + if(!found) + { + parent= parent->getPreviousNode(); + } + } + if(nullptr == result) + { + m_errors.insert( + Dice::ERROR_CODE::DIE_RESULT_EXPECTED, + QObject::tr(" The @ operator expects dice result. Please check the documentation to fix your command.")); + } + else + { + DiceResult* diceResult= dynamic_cast<DiceResult*>(result); + if(nullptr != diceResult) + { + for(auto& die : diceResult->getResultList()) + { + Die* tmpdie= new Die(*die); + //*tmpdie= *die; + m_diceResult->insertResult(tmpdie); + die->displayed(); + } + } + + m_result->setPrevious(previous->getResult()); + + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } + if(nullptr != diceResult) + { + for(int i= 0; i < diceResult->getResultList().size(); ++i) + { + Die* tmp= diceResult->getResultList().at(i); + Die* tmp2= m_diceResult->getResultList().at(i); + if(tmp->isHighlighted()) + { + tmp2->setHighlighted(true); + } + } + } + } +} + +ExecutionNode* JumpBackwardNode::getCopy() const +{ + JumpBackwardNode* node= new JumpBackwardNode(); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/jumpbackwardnode.h b/src/libparser/node/jumpbackwardnode.h new file mode 100644 index 0000000..598a540 --- /dev/null +++ b/src/libparser/node/jumpbackwardnode.h @@ -0,0 +1,68 @@ +/************************************************************************* + * Copyright (C) 2009 by Renaud Guezennec * + * * + * https://rolisteam.org/ * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published * + * by the Free Software Foundation; either version 2 of the License, * + * or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + *************************************************************************/ +#ifndef JUMPBACKWARDNODE_H +#define JUMPBACKWARDNODE_H + +#include "executionnode.h" +#include "result/diceresult.h" +/** + * @brief The JumpBackwardNode class is dedicated to change the previous dice of one dice option. + */ +class JumpBackwardNode : public ExecutionNode +{ +public: + /** + * @brief JumpBackwardNode allows to get result from remote node in the execution tree. + */ + JumpBackwardNode(); + /** + * @brief run - performs the actions + * @param previous + */ + virtual void run(ExecutionNode* previous= nullptr); + + /** + * @brief toString + * @return + */ + virtual QString toString(bool) const; + /** + * @brief getPriority + * @return + */ + virtual qint64 getPriority() const; + /** + * @brief generateDotTree + * @param s + */ + virtual void generateDotTree(QString& s); + /** + * @brief getCopy + * @return + */ + virtual ExecutionNode* getCopy() const; + +private: + DiceResult* m_diceResult; + ExecutionNode* m_backwardNode; +}; + +#endif // JUMPBACKWARDNODE_H diff --git a/src/libparser/node/keepdiceexecnode.cpp b/src/libparser/node/keepdiceexecnode.cpp new file mode 100644 index 0000000..b197822 --- /dev/null +++ b/src/libparser/node/keepdiceexecnode.cpp @@ -0,0 +1,131 @@ +/************************************************************************* + * Copyright (C) 2009 by Renaud Guezennec * + * * + * https://rolisteam.org/ * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published * + * by the Free Software Foundation; either version 2 of the License, * + * or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + *************************************************************************/ +#include <QList> + +#include "diceparser/parsingtoolbox.h" +#include "keepdiceexecnode.h" + +KeepDiceExecNode::KeepDiceExecNode() : m_diceResult(new DiceResult()) +{ + m_result= m_diceResult; +} +KeepDiceExecNode::~KeepDiceExecNode() {} +void KeepDiceExecNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr == previous || nullptr == m_numberOfDiceNode) + { + return; + } + m_numberOfDiceNode->run(previous); + auto lastnode= ParsingToolBox::getLeafNode(m_numberOfDiceNode); + if(nullptr == lastnode) + return; + auto result= lastnode->getResult(); + if(nullptr == result) + return; + if(!result->hasResultOfType(Dice::RESULT_TYPE::SCALAR)) + return; + + auto numberOfDice= result->getResult(Dice::RESULT_TYPE::SCALAR).toInt(); + + DiceResult* previousDiceResult= dynamic_cast<DiceResult*>(previous->getResult()); + m_result->setPrevious(previousDiceResult); + if(nullptr != previousDiceResult) + { + QList<Die*> diceList= previousDiceResult->getResultList(); + + if(numberOfDice < 0) + { + numberOfDice= diceList.size() + numberOfDice; + } + + QList<Die*> diceList3= diceList.mid(0, static_cast<int>(numberOfDice)); + QList<Die*> diceList2; + + for(Die* die : qAsConst(diceList3)) + { + Die* tmpdie= new Die(*die); + diceList2.append(tmpdie); + die->displayed(); + die->setSelected(false); + } + + if(numberOfDice > static_cast<qint64>(diceList.size())) + { + m_errors.insert(Dice::ERROR_CODE::TOO_MANY_DICE, + QObject::tr(" You ask to keep %1 dice but the result only has %2") + .arg(numberOfDice) + .arg(diceList.size())); + } + + for(auto& tmp : diceList.mid(static_cast<int>(numberOfDice), -1)) + { + tmp->setHighlighted(false); + } + + m_diceResult->setResultList(diceList2); + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } + } +} + +void KeepDiceExecNode::setDiceKeepNumber(ExecutionNode* n) +{ + m_numberOfDiceNode= n; +} +QString KeepDiceExecNode::toString(bool wl) const +{ + if(wl) + { + // auto param= m_numberOfDiceNode->toString(wl); + return QString("%1 [label=\"KeepDiceExecNode\"]").arg(m_id); + } + else + { + return m_id; + } +} +qint64 KeepDiceExecNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_previousNode) + { + priority= m_previousNode->getPriority(); + } + return priority; +} + +ExecutionNode* KeepDiceExecNode::getCopy() const +{ + KeepDiceExecNode* node= new KeepDiceExecNode(); + if(nullptr != m_numberOfDiceNode) + { + node->setDiceKeepNumber(m_numberOfDiceNode->getCopy()); + } + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/keepdiceexecnode.h b/src/libparser/node/keepdiceexecnode.h new file mode 100644 index 0000000..0dd6616 --- /dev/null +++ b/src/libparser/node/keepdiceexecnode.h @@ -0,0 +1,47 @@ +/************************************************************************* + * Copyright (C) 2009 by Renaud Guezennec * + * * + * https://rolisteam.org/ * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published * + * by the Free Software Foundation; either version 2 of the License, * + * or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + *************************************************************************/ +#ifndef KEEPDICEEXECNODE_H +#define KEEPDICEEXECNODE_H + +#include "executionnode.h" +#include "result/diceresult.h" +/** + * @brief The KeepDiceExecNode class splits the dice result to get the m_numberOfDice dice from the beginning of the + * dice result. Usually the pervious node of an KeepDiceExecNode is an SortNode. + */ +class KeepDiceExecNode : public ExecutionNode +{ +public: + KeepDiceExecNode(); + virtual ~KeepDiceExecNode(); + + virtual void run(ExecutionNode* previous); + virtual void setDiceKeepNumber(ExecutionNode* valueNode ); + virtual QString toString(bool) const; + virtual qint64 getPriority() const; + virtual ExecutionNode* getCopy() const; + +private: + ExecutionNode* m_numberOfDiceNode = nullptr; + DiceResult* m_diceResult; +}; + +#endif // KEEPDICEEXECNODE_H diff --git a/src/libparser/node/listaliasnode.cpp b/src/libparser/node/listaliasnode.cpp new file mode 100644 index 0000000..c3f6d31 --- /dev/null +++ b/src/libparser/node/listaliasnode.cpp @@ -0,0 +1,85 @@ +/************************************************************************* + * Copyright (C) 2009 by Renaud Guezennec * + * * + * https://rolisteam.org/ * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published * + * by the Free Software Foundation; either version 2 of the License, * + * or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + *************************************************************************/ +#include "listaliasnode.h" + +ListAliasNode::ListAliasNode(const QList<DiceAlias*>& apAlias) : m_aliasList(apAlias) +{ + m_result= new StringResult(); +} +void ListAliasNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + StringResult* txtResult= dynamic_cast<StringResult*>(m_result); + txtResult->setHighLight(false); + + txtResult->addText(buildList()); + txtResult->finished(); + if(nullptr != previous) + { + // txtResult->setText(previous->getHelp()); + m_result->setPrevious(previous->getResult()); + } + + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} +QString ListAliasNode::buildList() const +{ + QString result(QObject::tr("List of Alias:\n")); + for(auto& key : m_aliasList) + { + result+= QString("%1 : %2 # %3\n").arg(key->pattern(), key->command(), key->comment()); + } + return result; +} +QString ListAliasNode::toString(bool wl) const +{ + QStringList resultList; + for(auto& key : m_aliasList) + { + resultList << "{" << key->pattern() << key->command() << "}"; + } + + if(wl) + { + return QString("%1 [label=\"ListAliasNode %2\"]").arg(m_id, resultList.join(",")); + } + else + { + return m_id; + } +} +qint64 ListAliasNode::getPriority() const +{ + return 0; +} + +ExecutionNode* ListAliasNode::getCopy() const +{ + ListAliasNode* node= new ListAliasNode(m_aliasList); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/listaliasnode.h b/src/libparser/node/listaliasnode.h new file mode 100644 index 0000000..2a6f96e --- /dev/null +++ b/src/libparser/node/listaliasnode.h @@ -0,0 +1,64 @@ +/************************************************************************* + * Copyright (C) 2009 by Renaud Guezennec * + * * + * https://rolisteam.org/ * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published * + * by the Free Software Foundation; either version 2 of the License, * + * or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + *************************************************************************/ +#ifndef LISTALIASNODE_H +#define LISTALIASNODE_H + +#include <diceparser/dicealias.h> + +#include "executionnode.h" +#include "result/stringresult.h" + +/** + * @brief The ListAliasNode class is dedicated to display the list of the current aliases. + */ +class ListAliasNode : public ExecutionNode +{ +public: + ListAliasNode(const QList<DiceAlias*>& mapAlias); + /** + * @brief run + * @param previous + */ + virtual void run(ExecutionNode* previous= nullptr); + + /** + * @brief toString + * @return + */ + virtual QString toString(bool) const; + /** + * @brief buildList + * @return + */ + virtual QString buildList() const; + /** + * @brief getPriority + * @return + */ + virtual qint64 getPriority() const; + + virtual ExecutionNode* getCopy() const; + +private: + const QList<DiceAlias*>& m_aliasList; +}; + +#endif // LISTALIASNODE_H diff --git a/src/libparser/node/listsetrollnode.cpp b/src/libparser/node/listsetrollnode.cpp new file mode 100644 index 0000000..2cee645 --- /dev/null +++ b/src/libparser/node/listsetrollnode.cpp @@ -0,0 +1,190 @@ +/************************************************************************* + * Copyright (C) 2009 by Renaud Guezennec * + * * + * https://rolisteam.org/ * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published * + * by the Free Software Foundation; either version 2 of the License, * + * or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + *************************************************************************/ +#include "listsetrollnode.h" +#include "die.h" + +#include <QDebug> + +ListSetRollNode::ListSetRollNode() : m_diceResult(new DiceResult()), m_stringResult(new StringResult()), m_unique(false) +{ + m_result= m_stringResult; +} +ListSetRollNode::~ListSetRollNode() +{ + if(nullptr != m_diceResult) + { + delete m_diceResult; + m_diceResult= nullptr; + } +} + +QStringList ListSetRollNode::getList() const +{ + return m_values; +} +QString ListSetRollNode::toString(bool wl) const +{ + if(wl) + { + return QString("%1 [label=\"ListSetRoll list:%2\"]").arg(m_id, m_values.join(",")); + } + else + { + return m_id; + } +} +qint64 ListSetRollNode::getPriority() const +{ + qint64 priority= 4; + return priority; +} +void ListSetRollNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr != previous) + { + Result* result= previous->getResult(); + if(nullptr != result) + { + quint64 diceCount= result->getResult(Dice::RESULT_TYPE::SCALAR).toReal(); + if(diceCount > static_cast<quint64>(m_values.size()) && m_unique) + { + m_errors.insert(Dice::ERROR_CODE::TOO_MANY_DICE, + QObject::tr("More unique values asked than possible values (L operator)")); + } + else + { + m_result->setPrevious(result); + for(quint64 i= 0; i < diceCount; ++i) + { + QStringList rollResult; + Die* die= new Die(); + computeFacesNumber(die); + die->roll(); + m_diceResult->insertResult(die); + getValueFromDie(die, rollResult); + for(auto const& str : qAsConst(rollResult)) + { + m_stringResult->addText(str); + } + } + m_stringResult->finished(); + } + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } + } + } +} +void ListSetRollNode::setListValue(QStringList lirs) +{ + m_values= lirs; +} +void ListSetRollNode::setUnique(bool u) +{ + m_unique= u; +} +void ListSetRollNode::setNoComma(bool b) +{ + if(m_stringResult) + m_stringResult->setNoComma(b); +} +void ListSetRollNode::setRangeList(QList<Range>& ranges) +{ + m_rangeList= ranges; +} +void ListSetRollNode::computeFacesNumber(Die* die) +{ + if(m_rangeList.isEmpty()) + { + die->setMaxValue(m_values.size()); + } + else + { + Q_ASSERT(m_values.size() == m_rangeList.size()); + qint64 max; + int i= 0; + for(Range& range : m_rangeList) + { + if(((i == 0) || (max < range.getEnd())) && (range.isFullyDefined())) + { + max= range.getEnd(); + } + ++i; + } + die->setMaxValue(max); + } +} +void ListSetRollNode::getValueFromDie(Die* die, QStringList& rollResult) +{ + if(m_rangeList.isEmpty()) + { + if(die->getValue() - 1 < m_values.size()) + { + auto str= m_values[die->getValue() - 1]; + while(m_unique && rollResult.contains(str)) + { + die->roll(false); + str= m_values[die->getValue() - 1]; + } + rollResult << str; + } + } + else + { + Q_ASSERT(m_values.size() == m_rangeList.size()); + bool found= false; + while(!found) + { + int i= 0; + for(Range& range : m_rangeList) + { + auto it= std::find(m_rangeIndexResult.begin(), m_rangeIndexResult.end(), i); + auto isValid= range.hasValid(die, false); + if((isValid && !m_unique) || (isValid && it == m_rangeIndexResult.end())) + { + m_rangeIndexResult.push_back(i); + rollResult << m_values[i]; + found= true; + } + ++i; + } + if(!found) + { + die->roll(false); + } + } + } +} +ExecutionNode* ListSetRollNode::getCopy() const +{ + ListSetRollNode* node= new ListSetRollNode(); + QList<Range> dataList= m_rangeList; + node->setRangeList(dataList); + node->setUnique(m_unique); + node->setListValue(m_values); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/listsetrollnode.h b/src/libparser/node/listsetrollnode.h new file mode 100644 index 0000000..a6c5e1a --- /dev/null +++ b/src/libparser/node/listsetrollnode.h @@ -0,0 +1,62 @@ +/************************************************************************* + * Copyright (C) 2009 by Renaud Guezennec * + * * + * https://rolisteam.org/ * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published * + * by the Free Software Foundation; either version 2 of the License, * + * or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + *************************************************************************/ +#ifndef LISTSETROLLNODE_H +#define LISTSETROLLNODE_H + +#include <QStringList> + +#include "executionnode.h" +#include "range.h" +#include "result/diceresult.h" +#include "result/stringresult.h" +/** + * @brief The ListSetRollNode class is dedicated to pick up item from list. + */ +class ListSetRollNode : public ExecutionNode +{ +public: + ListSetRollNode(); + virtual ~ListSetRollNode(); + virtual void run(ExecutionNode* previous= nullptr); + virtual QString toString(bool) const; + virtual qint64 getPriority() const; + QStringList getList() const; + + void setListValue(QStringList); + void setUnique(bool); + void setNoComma(bool); + void setRangeList(QList<Range>&); + virtual ExecutionNode* getCopy() const; + +private: + void getValueFromDie(Die* die, QStringList& rollResult); + void computeFacesNumber(Die* die); + +private: + QStringList m_values; + DiceResult* m_diceResult; + StringResult* m_stringResult; + std::vector<int> m_rangeIndexResult; + bool m_unique; + QList<Range> m_rangeList; +}; + +#endif // LISTSETROLLNODE_H diff --git a/src/libparser/node/mergenode.cpp b/src/libparser/node/mergenode.cpp new file mode 100644 index 0000000..096bb8c --- /dev/null +++ b/src/libparser/node/mergenode.cpp @@ -0,0 +1,150 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "mergenode.h" + +#include <diceparser/parsingtoolbox.h> + +MergeNode::MergeNode() : m_diceResult(new DiceResult()) +{ + m_result= m_diceResult; +} +void MergeNode::run(ExecutionNode* previous) +{ + if(nullptr == previous) + { + m_errors.insert(Dice::ERROR_CODE::NO_PREVIOUS_ERROR, QObject::tr("No previous node before Merge operator")); + return; + } + + m_previousNode= previous; + m_result->setPrevious(previous->getResult()); + ExecutionNode* previousLast= nullptr; + std::vector<Result*> pastResult; + for(auto start : *m_startList) + { + ExecutionNode* last= getLatestNode(start); + if(nullptr == last || nullptr == previousLast) + { + previousLast= last; + continue; + } + + auto startResult= start->getResult(); + if(nullptr == startResult) + continue; + + startResult->setPrevious(previousLast->getResult()); + previousLast->setNextNode(start); + + previousLast= last; + Result* tmpResult= last->getResult(); + while(nullptr != tmpResult) + { + DiceResult* dice= dynamic_cast<DiceResult*>(tmpResult); + if(nullptr != dice) + { + ///@todo TODO improve here to set homogeneous while is really + m_diceResult->setHomogeneous(false); + for(auto& die : dice->getResultList()) + { + if(!m_diceResult->getResultList().contains(die) && (!die->hasBeenDisplayed())) + { + Die* tmpdie= new Die(*die); + die->displayed(); + m_diceResult->getResultList().append(tmpdie); + } + } + } + auto it= std::find_if(pastResult.begin(), pastResult.end(), + [tmpResult](const Result* a) { return (a == tmpResult->getPrevious()); }); + if(it == pastResult.end()) + { + pastResult.push_back(previousLast->getResult()); + tmpResult= tmpResult->getPrevious(); + } + else + { + tmpResult->setPrevious(nullptr); + tmpResult= nullptr; + } + } + } + + auto first= m_startList->front(); + m_startList->clear(); + m_startList->push_back(first); + + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} +#include <QDebug> +ExecutionNode* MergeNode::getLatestNode(ExecutionNode* node) +{ + ExecutionNode* next= node; + while(nullptr != next->getNextNode() && (next->getNextNode() != this)) + { + // qDebug() << "find latest node" << next->toString(true) << next->getNextNode()->toString(true); + next= next->getNextNode(); + } + return next; +} +QString MergeNode::toString(bool withLabel) const +{ + if(withLabel) + { + return QString("%1 [label=\"Merge Node\"]").arg(m_id); + } + else + { + return m_id; + } +} +qint64 MergeNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_previousNode) + { + priority= m_previousNode->getPriority(); + } + return priority; +} +ExecutionNode* MergeNode::getCopy() const +{ + MergeNode* node= new MergeNode(); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} + +std::vector<ExecutionNode*>* MergeNode::getStartList() const +{ + return m_startList; +} + +void MergeNode::setStartList(std::vector<ExecutionNode*>* startList) +{ + m_startList= startList; +} diff --git a/src/libparser/node/mergenode.h b/src/libparser/node/mergenode.h new file mode 100644 index 0000000..515a2e9 --- /dev/null +++ b/src/libparser/node/mergenode.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef MERGENODE_H +#define MERGENODE_H + +#include "node/executionnode.h" +#include "result/diceresult.h" + +/** + * @brief The MergeNode class is an ExecutionNode. It is dedicated to merge result of several commands. + */ +class MergeNode : public ExecutionNode +{ +public: + MergeNode(); + void run(ExecutionNode* previous); + virtual QString toString(bool withLabel) const; + virtual qint64 getPriority() const; + virtual ExecutionNode* getCopy() const; + std::vector<ExecutionNode*>* getStartList() const; + void setStartList(std::vector<ExecutionNode*>* startList); + +private: + ExecutionNode* getLatestNode(ExecutionNode* node); + +private: + DiceResult* m_diceResult= nullptr; + std::vector<ExecutionNode*>* m_startList= nullptr; +}; + +#endif // NUMBERNODE_H diff --git a/src/libparser/node/node.pri b/src/libparser/node/node.pri new file mode 100644 index 0000000..6cf7005 --- /dev/null +++ b/src/libparser/node/node.pri @@ -0,0 +1,33 @@ +HEADERS += \ + $$PWD/dicerollernode.h \ + $$PWD/executionnode.h \ + $$PWD/rerolldicenode.h \ + $$PWD/startingnode.h \ + $$PWD/scalaroperatornode.h \ + $$PWD/numbernode.h \ + $$PWD/sortresult.h \ + $$PWD/keepdiceexecnode.h \ + $$PWD/countexecutenode.h \ + $$PWD/explodedicenode.h \ + $$PWD/parenthesesnode.h \ + $$PWD/helpnode.h \ + $$PWD/jumpbackwardnode.h \ + $$PWD/listsetrollnode.h\ + $$PWD/listaliasnode.h + +SOURCES += \ + $$PWD/dicerollernode.cpp \ + $$PWD/executionnode.cpp \ + $$PWD/startingnode.cpp \ + $$PWD/rerolldicenode.cpp \ + $$PWD/scalaroperatornode.cpp \ + $$PWD/numbernode.cpp \ + $$PWD/sortresult.cpp \ + $$PWD/keepdiceexecnode.cpp \ + $$PWD/countexecutenode.cpp \ + $$PWD/explodedicenode.cpp \ + $$PWD/parenthesesnode.cpp \ + $$PWD/helpnode.cpp \ + $$PWD/jumpbackwardnode.cpp \ + $$PWD/listsetrollnode.cpp\ + $$PWD/listaliasnode.cpp diff --git a/src/libparser/node/numbernode.cpp b/src/libparser/node/numbernode.cpp new file mode 100644 index 0000000..e50656e --- /dev/null +++ b/src/libparser/node/numbernode.cpp @@ -0,0 +1,84 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "numbernode.h" + +NumberNode::NumberNode() : m_scalarResult(new ScalarResult()) +{ + m_result= m_scalarResult; +} +NumberNode::~NumberNode() +{ + /*if( nullptr != m_scalarResult) + { + delete m_scalarResult; + m_scalarResult = nullptr; + }*/ +} + +void NumberNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr != previous) + { + m_result->setPrevious(previous->getResult()); + } + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} + +void NumberNode::setNumber(qint64 a) +{ + m_scalarResult->setValue(a); + m_number= a; +} +QString NumberNode::toString(bool withLabel) const +{ + if(withLabel) + { + return QString("%1 [label=\"NumberNode %2\"]").arg(m_id).arg(m_number); + } + else + { + return m_id; + } +} +qint64 NumberNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_nextNode) + { + priority= m_nextNode->getPriority(); + } + return priority; +} +ExecutionNode* NumberNode::getCopy() const +{ + NumberNode* node= new NumberNode(); + node->setNumber(m_number); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/numbernode.h b/src/libparser/node/numbernode.h new file mode 100644 index 0000000..02df984 --- /dev/null +++ b/src/libparser/node/numbernode.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef NUMBERNODE_H +#define NUMBERNODE_H + +#include "node/executionnode.h" +#include "result/scalarresult.h" + +/** + * @brief The NumberNode class is an ExecutionNode. It is dedicated to store number. + */ +class NumberNode : public ExecutionNode +{ +public: + NumberNode(); + virtual ~NumberNode(); + void run(ExecutionNode* previous); + void setNumber(qint64); + virtual QString toString(bool withLabel) const; + virtual qint64 getPriority() const; + virtual ExecutionNode* getCopy() const; + +private: + qint64 m_number; + ScalarResult* m_scalarResult; +}; + +#endif // NUMBERNODE_H diff --git a/src/libparser/node/occurencecountnode.cpp b/src/libparser/node/occurencecountnode.cpp new file mode 100644 index 0000000..fc5c2f2 --- /dev/null +++ b/src/libparser/node/occurencecountnode.cpp @@ -0,0 +1,185 @@ +/*************************************************************************** + * Copyright (C) 2018 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "occurencecountnode.h" +#include "result/diceresult.h" +#include "result/stringresult.h" +#include "validatorlist.h" +#include <QVector> + +OccurenceCountNode::OccurenceCountNode() : ExecutionNode() {} + +void OccurenceCountNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + std::map<qint64, qint64> mapOccurence; + if(nullptr == m_previousNode) + return; + + DiceResult* previousDiceResult= dynamic_cast<DiceResult*>(m_previousNode->getResult()); + if(nullptr == previousDiceResult) + return; + + auto const& diceList= previousDiceResult->getResultList(); + QVector<qint64> vec; + + for(auto dice : diceList) + { + auto val= dice->getValue(); + + vec << val; + auto it= mapOccurence.find(val); + if(it == mapOccurence.end()) + mapOccurence[val]= 1; + else + mapOccurence[val]+= 1; + } + + std::sort(vec.begin(), vec.end()); + if(nullptr == m_nextNode) + { + runForStringResult(mapOccurence, vec); + } + else + { + runForDiceResult(mapOccurence); + } +} +QString OccurenceCountNode::toString(bool label) const +{ + if(label) + { + return QString("%1 [label=\"OccurenceCountNode %2\"]").arg(m_id); + } + else + { + return m_id; + } +} +ExecutionNode* OccurenceCountNode::getCopy() const +{ + return nullptr; +} +qint64 OccurenceCountNode::getPriority() const +{ + qint64 priority= 0; + + if(nullptr != m_previousNode) + { + priority= m_previousNode->getPriority(); + } + return priority; +} + +qint64 OccurenceCountNode::getWidth() const +{ + return m_width; +} + +void OccurenceCountNode::setWidth(const qint64& width) +{ + m_width= width; +} + +qint64 OccurenceCountNode::getHeight() const +{ + return m_height; +} + +void OccurenceCountNode::setHeight(const qint64& height) +{ + m_height= height; +} + +ValidatorList* OccurenceCountNode::getValidatorList() const +{ + return m_validatorList; +} + +void OccurenceCountNode::setValidatorList(ValidatorList* validatorlist) +{ + m_validatorList= validatorlist; +} +void OccurenceCountNode::runForStringResult(const std::map<qint64, qint64>& mapOccurence, QVector<qint64>& vec) +{ + m_stringResult= new StringResult(); + m_result= m_stringResult; + QStringList list; + for(auto key : mapOccurence) + { + if(nullptr != m_validatorList) + { + Die die; + die.insertRollValue(key.first); + if(!m_validatorList->hasValid(&die, true)) + continue; + } + + if(key.second < m_width) + continue; + + if(key.first >= m_height) + list << QStringLiteral("%1x%2").arg(key.second).arg(key.first); + } + + QStringList resultList; + std::for_each(vec.begin(), vec.end(), [&resultList](qint64 val) { resultList << QString::number(val); }); + + QString result; + + if(!list.isEmpty()) + result= list.join(','); + else + result= QObject::tr("No matching result"); + + m_stringResult->addText(QStringLiteral("%1 - [%2]").arg(result).arg(resultList.join(','))); + m_stringResult->finished(); +} +void OccurenceCountNode::runForDiceResult(const std::map<qint64, qint64>& mapOccurence) +{ + m_diceResult= new DiceResult(); + m_result= m_diceResult; + QStringList list; + for(auto key : mapOccurence) + { + if(nullptr != m_validatorList) + { + Die die; + die.insertRollValue(key.first); + if(!m_validatorList->hasValid(&die, true)) + continue; + } + + if(key.second < m_width) + continue; + + if(key.first >= m_height) + { + // list << QStringLiteral("%1x%2").arg(key.second).arg(key.first); + Die* die= new Die(); + die->insertRollValue(key.second * key.first); + m_diceResult->insertResult(die); + } + } + + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} diff --git a/src/libparser/node/occurencecountnode.h b/src/libparser/node/occurencecountnode.h new file mode 100644 index 0000000..4801bfb --- /dev/null +++ b/src/libparser/node/occurencecountnode.h @@ -0,0 +1,60 @@ +/*************************************************************************** + * Copyright (C) 2018 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef OCCURENCECOUNTNODE_H +#define OCCURENCECOUNTNODE_H + +#include "executionnode.h" + +class ValidatorList; +class StringResult; +class DiceResult; +class OccurenceCountNode : public ExecutionNode +{ +public: + OccurenceCountNode(); + + void run(ExecutionNode* previous= nullptr); + virtual QString toString(bool withLabel) const; + + ExecutionNode* getCopy() const; + qint64 getPriority() const; + + qint64 getWidth() const; + void setWidth(const qint64& width); + + qint64 getHeight() const; + void setHeight(const qint64& height); + + ValidatorList* getValidatorList() const; + void setValidatorList(ValidatorList* validator); + +private: + void runForStringResult(const std::map<qint64, qint64>& mapOccurence, QVector<qint64>& vec); + void runForDiceResult(const std::map<qint64, qint64>& mapOccurence); + +private: + qint64 m_width= 1; + qint64 m_height= 0; + ValidatorList* m_validatorList= nullptr; + StringResult* m_stringResult= nullptr; + DiceResult* m_diceResult= nullptr; +}; + +#endif // OCCURENCECOUNTNODE_H diff --git a/src/libparser/node/paintnode.cpp b/src/libparser/node/paintnode.cpp new file mode 100644 index 0000000..22c020e --- /dev/null +++ b/src/libparser/node/paintnode.cpp @@ -0,0 +1,125 @@ +/*************************************************************************** + * Copyright (C) 2015 by Renaud Guezennec * + * http:://www.rolisteam.org/contact * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "paintnode.h" + +ColorItem::ColorItem(QString str, int val) : m_colorNumber(val), m_color(str) {} + +int ColorItem::colorNumber() const +{ + return m_colorNumber; +} + +void ColorItem::setColorNumber(int colorNumber) +{ + m_colorNumber= colorNumber; +} + +QString ColorItem::color() const +{ + return m_color; +} + +void ColorItem::setColor(const QString& color) +{ + m_color= color; +} + +/////////////////////////////////// +/// @brief PainterNode::PainterNode +/////////////////////////////////// + +PainterNode::PainterNode() : ExecutionNode() +{ + m_nextNode= nullptr; +} + +PainterNode::~PainterNode() +{ + m_result= nullptr; +} + +void PainterNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr == previous) + { + m_errors.insert(Dice::ERROR_CODE::NO_PREVIOUS_ERROR, QObject::tr("No previous node before Paint operator")); + return; + } + Result* previousResult= previous->getResult(); + if(nullptr == previousResult) + return; + + m_diceResult= dynamic_cast<DiceResult*>(previousResult->getCopy()); + if(nullptr != m_diceResult) + { + QList<Die*> diceList= m_diceResult->getResultList(); + int pastDice= 0; + for(ColorItem& item : m_colors) + { + int current= item.colorNumber(); + QList<Die*>::iterator it; + for(it= diceList.begin() + pastDice; it != diceList.end() && current > 0; ++it) + { + (*it)->setColor(item.color()); + --current; + ++pastDice; + } + } + m_diceResult->setPrevious(previousResult); + m_result= m_diceResult; + } + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} + +QString PainterNode::toString(bool wl) const +{ + if(wl) + { + return QString("%1 [label=\"PainterNode\"]").arg(m_id); + } + else + { + return m_id; + } +} + +qint64 PainterNode::getPriority() const +{ + return 4; +} + +void PainterNode::insertColorItem(QString color, int value) +{ + ColorItem item(color, value); + m_colors.append(item); +} +ExecutionNode* PainterNode::getCopy() const +{ + PainterNode* node= new PainterNode(); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/paintnode.h b/src/libparser/node/paintnode.h new file mode 100644 index 0000000..06d849e --- /dev/null +++ b/src/libparser/node/paintnode.h @@ -0,0 +1,60 @@ +/*************************************************************************** + * Copyright (C) 2015 by Renaud Guezennec * + * http:://www.rolisteam.org/contact * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef PAINTERNODE_H +#define PAINTERNODE_H + +#include "executionnode.h" +#include "result/diceresult.h" +#include <QString> + +class ColorItem +{ +public: + ColorItem(QString str, int val); + int colorNumber() const; + void setColorNumber(int colorNumber); + + QString color() const; + void setColor(const QString& color); + +private: + int m_colorNumber; + QString m_color; +}; +/** + * @brief The PainterNode class means to manage color attribute of dice. + */ +class PainterNode : public ExecutionNode +{ +public: + PainterNode(); + virtual ~PainterNode(); + virtual void run(ExecutionNode* previous= nullptr); + virtual QString toString(bool) const; + virtual qint64 getPriority() const; + void insertColorItem(QString color, int value); + virtual ExecutionNode* getCopy() const; + +protected: + QList<ColorItem> m_colors; + DiceResult* m_diceResult= nullptr; +}; + +#endif diff --git a/src/libparser/node/parenthesesnode.cpp b/src/libparser/node/parenthesesnode.cpp new file mode 100644 index 0000000..9557536 --- /dev/null +++ b/src/libparser/node/parenthesesnode.cpp @@ -0,0 +1,119 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "parenthesesnode.h" + +ParenthesesNode::ParenthesesNode() : m_internalNode(nullptr) {} +void ParenthesesNode::setInternelNode(ExecutionNode* node) +{ + m_internalNode= node; +} +void ParenthesesNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr != m_internalNode) + { + m_internalNode->run(this); + ExecutionNode* temp= m_internalNode; + while(nullptr != temp->getNextNode()) + { + temp= temp->getNextNode(); + } + m_result= temp->getResult(); + } + + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} +QString ParenthesesNode::toString(bool b) const +{ + if(b) + { + return QString("%1 [label=\"ParenthesesNode\"]").arg(m_id); + } + else + { + return m_id; + } +} +qint64 ParenthesesNode::getPriority() const +{ + qint64 priority= 3; + return priority; +} +ExecutionNode* ParenthesesNode::getCopy() const +{ + ParenthesesNode* node= new ParenthesesNode(); + if(nullptr != m_internalNode) + { + node->setInternelNode(m_internalNode->getCopy()); + } + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} + +void ParenthesesNode::generateDotTree(QString& s) +{ + auto str= toString(true); + if(s.contains(str)) + return; + s.append(str); + s.append(";\n"); + + if(nullptr != m_internalNode) + { + s.append(toString(false)); + s.append(" -> "); + s.append(m_internalNode->toString(false)); + s.append("[label=\"internal\"];\n"); + m_internalNode->generateDotTree(s); + } + + if(nullptr != m_nextNode) + { + s.append(toString(false)); + s.append(" -> "); + s.append(m_nextNode->toString(false)); + s.append(" [label=\"next\"];\n"); + // s.append(" [label=\"nextNode\"];\n"); + m_nextNode->generateDotTree(s); + } + else + { + s.append(toString(false)); + s.append(" -> "); + s.append("nullptr;\n"); + } + if(nullptr != m_result) + { + s.append(toString(false)); + s.append(" ->"); + s.append(m_result->toString(false)); + s.append(" [label=\"Result\", style=\"dashed\"];\n"); + if(nullptr == m_nextNode) + m_result->generateDotTree(s); + } +} diff --git a/src/libparser/node/parenthesesnode.h b/src/libparser/node/parenthesesnode.h new file mode 100644 index 0000000..153dfc1 --- /dev/null +++ b/src/libparser/node/parenthesesnode.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef PARENTHESESNODE_H +#define PARENTHESESNODE_H + +#include "executionnode.h" +/** + * @brief The ParenthesesNode class is an ExecutionNode. It is dedicated to manage expression which was inside + * ParenthesesNode. It is acting just like an StartingNode by for an internal execution tree. + */ +class ParenthesesNode : public ExecutionNode +{ +public: + ParenthesesNode(); + virtual void run(ExecutionNode* previous= nullptr); + + void setInternelNode(ExecutionNode* node); + virtual QString toString(bool) const; + virtual qint64 getPriority() const; + virtual ExecutionNode* getCopy() const; + virtual void generateDotTree(QString&); + +private: + ExecutionNode* m_internalNode; +}; + +#endif // PARENTHESESNODE_H diff --git a/src/libparser/node/repeaternode.cpp b/src/libparser/node/repeaternode.cpp new file mode 100644 index 0000000..f93a9fe --- /dev/null +++ b/src/libparser/node/repeaternode.cpp @@ -0,0 +1,162 @@ +/*************************************************************************** + * Copyright (C) 2019 by Renaud Guezennec * + * http://www.rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "node/repeaternode.h" + +#include "executionnode.h" +#include "result/scalarresult.h" +#include "result/stringresult.h" +#include <QDebug> +#include <diceparser/diceparserhelper.h> +#include <diceparser/parsingtoolbox.h> + +using InstructionSet= std::vector<ExecutionNode*>; + +QStringList allFirstResultAsString(const InstructionSet& startingNodes, bool& hasAlias) +{ + ParsingToolBox parsingBox; + // QStringList allResult; + QStringList stringListResult; + for(auto node : startingNodes) + { + auto pair= parsingBox.hasResultOfType(Dice::RESULT_TYPE::STRING, node); + auto pairStr= parsingBox.hasResultOfType(Dice::RESULT_TYPE::SCALAR, node, true); + if(pair.first) + { + stringListResult << pair.second.toString(); + hasAlias= true; + } + else if(pairStr.first) + { + stringListResult << QString::number(pairStr.second.toReal()); + hasAlias= true; + } + } + return stringListResult; +} + +std::vector<ExecutionNode*> makeCopy(std::vector<ExecutionNode*> cmds) +{ + std::vector<ExecutionNode*> copy; + std::transform(cmds.begin(), cmds.end(), std::back_inserter(copy), + [](ExecutionNode* node) { return node->getCopy(); }); + return copy; +} + +RepeaterNode::RepeaterNode() {} + +void RepeaterNode::run(ExecutionNode* previousNode) +{ + m_previousNode= previousNode; + + if(nullptr == m_times || m_cmd.empty()) + return; + + m_times->run(this); + m_times= ParsingToolBox::getLeafNode(m_times); + auto times= m_times->getResult(); + if(!times) + return; + + std::vector<InstructionSet> m_startingNodes; + auto timeCount= times->getResult(Dice::RESULT_TYPE::SCALAR).toInt(); + auto cmd= makeCopy(m_cmd); + std::vector<Result*> resultVec; + for(int i= 0; i < timeCount; ++i) + { + m_startingNodes.push_back(cmd); + std::for_each(cmd.begin(), cmd.end(), + [this, &resultVec](ExecutionNode* node) + { + node->run(this); + auto end= ParsingToolBox::getLeafNode(node); + auto leafResult= end->getResult(); + + if(nullptr == leafResult) + return; + + resultVec.push_back(leafResult); + }); + cmd= makeCopy(m_cmd); + } + if(m_sumAll) + { + auto scalar= new ScalarResult(); + qreal value= 0.0; + std::for_each(resultVec.begin(), resultVec.end(), + [&value](Result* result) { value+= result->getResult(Dice::RESULT_TYPE::SCALAR).toDouble(); }); + scalar->setValue(value); + m_result= scalar; + } + else + { + auto string= new StringResult(); + + QStringList listOfStrResult; + for(auto instructions : m_startingNodes) + { + ParsingToolBox parsingBox; + parsingBox.setStartNodes(instructions); + auto finalString + = parsingBox.finalStringResult([](const QString& result, const QString&, bool) { return result; }); + listOfStrResult << finalString; + } + if(!listOfStrResult.isEmpty()) + string->addText(listOfStrResult.join('\n')); + + m_result= string; + + // qDebug().noquote() << listOfStrResult.join('\n'); + } + + if(nullptr != m_nextNode) + m_nextNode->run(this); +} + +QString RepeaterNode::toString(bool withLabel) const +{ + return withLabel ? QStringLiteral("") : QStringLiteral(""); +} + +qint64 RepeaterNode::getPriority() const +{ + return 4; +} + +ExecutionNode* RepeaterNode::getCopy() const +{ + return nullptr; +} + +void RepeaterNode::setCommand(const std::vector<ExecutionNode*>& cmd) +{ + m_cmd= cmd; +} + +void RepeaterNode::setTimeNode(ExecutionNode* time) +{ + m_times= time; +} + +void RepeaterNode::setSumAll(bool b) +{ + m_sumAll= b; +} diff --git a/src/libparser/node/repeaternode.h b/src/libparser/node/repeaternode.h new file mode 100644 index 0000000..fa1a50a --- /dev/null +++ b/src/libparser/node/repeaternode.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2019 by Renaud Guezennec * + * http://www.rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef REPEATER_NODE_H +#define REPEATER_NODE_H + +#include "node/executionnode.h" +#include <memory> + +class RepeaterNode : public ExecutionNode +{ +public: + RepeaterNode(); + void run(ExecutionNode* previous) override; + virtual QString toString(bool withLabel) const override; + virtual qint64 getPriority() const override; + + virtual ExecutionNode* getCopy() const override; + + void setCommand(const std::vector<ExecutionNode*>& node); + void setTimeNode(ExecutionNode* times); + void setSumAll(bool b); + +private: + std::vector<ExecutionNode*> m_cmd; + ExecutionNode* m_times= nullptr; + bool m_sumAll= false; +}; + +#endif // REPEATER_NODE_H diff --git a/src/libparser/node/replacevaluenode.cpp b/src/libparser/node/replacevaluenode.cpp new file mode 100644 index 0000000..c313fb0 --- /dev/null +++ b/src/libparser/node/replacevaluenode.cpp @@ -0,0 +1,134 @@ +/*************************************************************************** + * Copyright (C) 2021 by Renaud Guezennec * + * http://www.rolisteam.org/contact * + * * + * This software is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "replacevaluenode.h" + +#include "diceresult.h" +#include <QDebug> +#include <diceparser/parsingtoolbox.h> + +ReplaceValueNode::ReplaceValueNode() : m_diceResult(new DiceResult) +{ + m_result= m_diceResult; +} + +void ReplaceValueNode::setStopAtFirt(bool b) +{ + m_stopAtFirst= b; +} + +void ReplaceValueNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr == previous) + { + m_errors.insert(Dice::ERROR_CODE::NO_PREVIOUS_ERROR, + QStringLiteral("No previous node before Switch/Case operator")); + return; + } + auto previousResult= previous->getResult(); + m_result->setPrevious(previousResult); + + if(nullptr == previousResult + || (!previousResult->hasResultOfType(Dice::RESULT_TYPE::SCALAR) + && !previousResult->hasResultOfType(Dice::RESULT_TYPE::DICE_LIST))) + { + m_errors.insert(Dice::ERROR_CODE::NO_VALID_RESULT, + QStringLiteral("No scalar or dice result before Switch/Case operator")); + return; + } + + QList<Die*> dieList; + if(previousResult->hasResultOfType(Dice::RESULT_TYPE::DICE_LIST)) + { + auto diceResult= dynamic_cast<DiceResult*>(previousResult); + if(diceResult) + dieList.append(diceResult->getResultList()); + } + + for(auto die : dieList) + { + QStringList resultList; + for(auto const& info : qAsConst(m_branchList)) + { + if(info->validatorList) + { + auto res= info->validatorList->hasValid(die, false); + if(!res) + continue; + } + else if(!resultList.isEmpty()) + break; + + auto replaceValresult= info->node->getResult(); + if(replaceValresult) + die->replaceLastValue(replaceValresult->getResult(Dice::RESULT_TYPE::SCALAR).toInt()); + break; + } + m_diceResult->insertResult(die); + } + + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} + +QString ReplaceValueNode::toString(bool withLabel) const +{ + if(withLabel) + { + return QString("%1 [label=\"ReplaceValueNode\"]").arg(m_id); + } + else + { + return m_id; + } +} + +qint64 ReplaceValueNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_previousNode) + { + priority= m_previousNode->getPriority(); + } + return priority; +} + +ExecutionNode* ReplaceValueNode::getCopy() const +{ + ReplaceValueNode* node= new ReplaceValueNode(); + for(auto const& info : qAsConst(m_branchList)) + { + node->insertCase(info->node, info->validatorList); + } + + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} + +void ReplaceValueNode::insertCase(ExecutionNode* node, ValidatorList* validator) +{ + std::unique_ptr<Dice::CaseInfo> info(new Dice::CaseInfo{validator, node}); + m_branchList.push_back(std::move(info)); +} diff --git a/src/libparser/node/replacevaluenode.h b/src/libparser/node/replacevaluenode.h new file mode 100644 index 0000000..36bdec2 --- /dev/null +++ b/src/libparser/node/replacevaluenode.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2021 by Renaud Guezennec * + * http://www.rolisteam.org/contact * + * * + * This software is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef REPLACEVALUENODE_H +#define REPLACEVALUENODE_H + +#include <memory> +#include <vector> + +#include "executionnode.h" +#include "validatorlist.h" + +class DiceResult; +class ReplaceValueNode : public ExecutionNode +{ +public: + ReplaceValueNode(); + void setStopAtFirt(bool b); + + void run(ExecutionNode* previous= nullptr) override; + + QString toString(bool withLabel) const override; + qint64 getPriority() const override; + ExecutionNode* getCopy() const override; + + void insertCase(ExecutionNode* node, ValidatorList* validator); + +private: + std::vector<std::unique_ptr<Dice::CaseInfo>> m_branchList; + DiceResult* m_diceResult= nullptr; + bool m_stopAtFirst= false; +}; + +#endif // REPLACEVALUENODE_H diff --git a/src/libparser/node/rerolldicenode.cpp b/src/libparser/node/rerolldicenode.cpp new file mode 100644 index 0000000..fd8c258 --- /dev/null +++ b/src/libparser/node/rerolldicenode.cpp @@ -0,0 +1,148 @@ +#include <diceparser/parsingtoolbox.h> + +#include "rerolldicenode.h" +#include "validatorlist.h" +#include <utility> + +RerollDiceNode::RerollDiceNode(bool reroll, bool addingMode) + : m_diceResult(new DiceResult()), m_validatorList(nullptr), m_reroll(reroll), m_adding(addingMode) +{ + m_result= m_diceResult; +} +RerollDiceNode::~RerollDiceNode() +{ + if(nullptr != m_validatorList) + { + delete m_validatorList; + m_validatorList= nullptr; + } +} +void RerollDiceNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if((nullptr != previous) && (nullptr != previous->getResult())) + { + DiceResult* previous_result= dynamic_cast<DiceResult*>(previous->getResult()); + m_result->setPrevious(previous_result); + if(nullptr != previous_result) + { + for(auto& die : previous_result->getResultList()) + { + Die* tmpdie= new Die(*die); + m_diceResult->insertResult(tmpdie); + die->displayed(); + } + // m_diceResult->setResultList(list); + + QList<Die*>& list= m_diceResult->getResultList(); + QList<Die*> toRemove; + + for(auto& die : list) + { + bool finished= false; + auto state= m_validatorList->isValidRangeSize( + std::make_pair<qint64, qint64>(die->getBase(), die->getMaxValue())); + if((Dice::CONDITION_STATE::ALWAYSTRUE == state && m_adding) + || (!m_reroll && !m_adding && state == Dice::CONDITION_STATE::UNREACHABLE)) + { + m_errors.insert(Dice::ERROR_CODE::ENDLESS_LOOP_ERROR, + QObject::tr("Condition (%1) cause an endless loop with this dice: %2") + .arg(toString(true)) + .arg(QStringLiteral("d[%1,%2]") + .arg(static_cast<int>(die->getBase())) + .arg(static_cast<int>(die->getMaxValue())))); + continue; + } + while(m_validatorList->hasValid(die, false) && !finished) + { + if(m_instruction != nullptr) + { + m_instruction->run(this); + auto lastNode= ParsingToolBox::getLeafNode(m_instruction); + if(lastNode != nullptr) + { + auto lastResult= dynamic_cast<DiceResult*>(lastNode->getResult()); + if(lastResult != nullptr) + { + toRemove.append(die); + list.append(lastResult->getResultList()); + lastResult->clear(); + } + } + } + else + { + die->roll(m_adding); + } + if(m_reroll) + { + finished= true; + } + } + } + + for(auto die : toRemove) + { + list.removeOne(die); + } + + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } + } + else + { + m_errors.insert( + Dice::ERROR_CODE::DIE_RESULT_EXPECTED, + QObject::tr( + " The a operator expects dice result. Please check the documentation and fix your command.")); + } + } +} +void RerollDiceNode::setValidatorList(ValidatorList* val) +{ + m_validatorList= val; +} +QString RerollDiceNode::toString(bool wl) const +{ + if(wl) + { + return QString("%1 [label=\"RerollDiceNode validatior: %2\"]").arg(m_id, m_validatorList->toString()); + } + else + { + return m_id; + } + // return QString("RerollDiceNode [label=\"RerollDiceNode validatior:%1\""); +} +qint64 RerollDiceNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_nextNode) + { + priority= m_nextNode->getPriority(); + } + + return priority; +} +ExecutionNode* RerollDiceNode::getCopy() const +{ + RerollDiceNode* node= new RerollDiceNode(m_reroll, m_adding); + node->setValidatorList(m_validatorList); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} + +ExecutionNode* RerollDiceNode::getInstruction() const +{ + return m_instruction; +} + +void RerollDiceNode::setInstruction(ExecutionNode* instruction) +{ + m_instruction= instruction; +} diff --git a/src/libparser/node/rerolldicenode.h b/src/libparser/node/rerolldicenode.h new file mode 100644 index 0000000..68b732e --- /dev/null +++ b/src/libparser/node/rerolldicenode.h @@ -0,0 +1,72 @@ +#ifndef REROLLDICENODE_H +#define REROLLDICENODE_H + +#include "executionnode.h" +#include "result/diceresult.h" + +class ValidatorList; +/** + * @brief The RerollDiceNode class reroll dice given a condition and replace(or add) the result. + */ +class RerollDiceNode : public ExecutionNode +{ +public: + /** + * @brief The ReRollMode enum + */ + enum ReRollMode + { + EQUAL, + LESSER, + GREATER + }; + /** + * @brief RerollDiceNode + * @param reroll If true reroll the dice only once, otherwise until the condition is false + */ + RerollDiceNode(bool reroll, bool addingMode); + + /** + * @brief ~RerollDiceNode + */ + virtual ~RerollDiceNode(); + /** + * @brief run + * @param previous + */ + virtual void run(ExecutionNode* previous); + + /** + * @brief setValidator + */ + virtual void setValidatorList(ValidatorList*); + /** + * @brief toString + * @return + */ + virtual QString toString(bool) const; + /** + * @brief getPriority + * @return + */ + virtual qint64 getPriority() const; + + /** + * @brief getCopy + * @return + */ + virtual ExecutionNode* getCopy() const; + + ExecutionNode* getInstruction() const; + void setInstruction(ExecutionNode* instruction); + +private: + DiceResult* m_diceResult= nullptr; + ValidatorList* m_validatorList= nullptr; + ExecutionNode* m_instruction= nullptr; + + const bool m_reroll; + const bool m_adding; +}; + +#endif // REROLLDICENODE_H diff --git a/src/libparser/node/scalaroperatornode.cpp b/src/libparser/node/scalaroperatornode.cpp new file mode 100644 index 0000000..c1c4dc5 --- /dev/null +++ b/src/libparser/node/scalaroperatornode.cpp @@ -0,0 +1,286 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "scalaroperatornode.h" + +#include "result/diceresult.h" +#include <QDebug> + +ScalarOperatorNode::ScalarOperatorNode() + : m_internalNode(nullptr), m_scalarResult(new ScalarResult()), m_arithmeticOperator(Dice::ArithmeticOperator::PLUS) +{ + m_result= m_scalarResult; +} +ScalarOperatorNode::~ScalarOperatorNode() +{ + if(nullptr != m_internalNode) + { + delete m_internalNode; + m_internalNode= nullptr; + } +} + +void ScalarOperatorNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr != m_internalNode) + { + m_internalNode->run(this); + } + if(nullptr != previous) + { + auto previousResult= previous->getResult(); + + if(nullptr != previousResult) + { + ExecutionNode* internal= m_internalNode; + if(nullptr != internal) + { + while(nullptr != internal->getNextNode()) + { + internal= internal->getNextNode(); + } + + Result* internalResult= internal->getResult(); + m_result->setPrevious(internalResult); + if(nullptr != m_internalNode->getResult()) + { + m_internalNode->getResult()->setPrevious(previousResult); + } + + if(internalResult == nullptr) + { + m_errors.insert(Dice::ERROR_CODE::NO_VALID_RESULT, + QObject::tr("No Valid result in arithmetic operation: %1").arg(toString(true))); + return; + } + + switch(m_arithmeticOperator) + { + case Dice::ArithmeticOperator::PLUS: + m_scalarResult->setValue(add(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(), + internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal())); + break; + case Dice::ArithmeticOperator::MINUS: + m_scalarResult->setValue(substract(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(), + internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal())); + break; + case Dice::ArithmeticOperator::MULTIPLICATION: + m_scalarResult->setValue(multiple(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(), + internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal())); + break; + case Dice::ArithmeticOperator::DIVIDE: + m_scalarResult->setValue(divide(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(), + internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal())); + break; + case Dice::ArithmeticOperator::INTEGER_DIVIDE: + m_scalarResult->setValue( + static_cast<int>(divide(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(), + internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal()))); + break; + case Dice::ArithmeticOperator::POW: + m_scalarResult->setValue(pow(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(), + internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal())); + break; + } + } + + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } + } + } +} +/*bool ScalarOperatorNode::setOperatorChar(QChar c) +{ + if(m_scalarOperationList.contains(c)) + { + m_operator = m_scalarOperationList.value(c); + return true; + } + return false; +}*/ + +void ScalarOperatorNode::setInternalNode(ExecutionNode* node) +{ + m_internalNode= node; +} +qint64 ScalarOperatorNode::add(qreal a, qreal b) +{ + return static_cast<qint64>(a + b); +} +qint64 ScalarOperatorNode::substract(qreal a, qreal b) +{ + return static_cast<qint64>(a - b); +} +qreal ScalarOperatorNode::divide(qreal a, qreal b) +{ + if(qFuzzyCompare(b, 0)) + { + m_errors.insert(Dice::ERROR_CODE::DIVIDE_BY_ZERO, QObject::tr("Division by zero")); + return 0; + } + return static_cast<qreal>(a / b); +} +qint64 ScalarOperatorNode::multiple(qreal a, qreal b) +{ + return static_cast<qint64>(a * b); +} +qint64 ScalarOperatorNode::pow(qreal a, qreal b) +{ + return static_cast<qint64>(std::pow(a, b)); +} +Dice::ArithmeticOperator ScalarOperatorNode::getArithmeticOperator() const +{ + return m_arithmeticOperator; +} + +void ScalarOperatorNode::setArithmeticOperator(const Dice::ArithmeticOperator& arithmeticOperator) +{ + m_arithmeticOperator= arithmeticOperator; +} + +QString ScalarOperatorNode::toString(bool wl) const +{ + QString op= ""; + switch(m_arithmeticOperator) + { + case Dice::ArithmeticOperator::PLUS: + op= "+"; + break; + case Dice::ArithmeticOperator::MINUS: + op= "-"; + break; + case Dice::ArithmeticOperator::MULTIPLICATION: + op= "*"; + break; + case Dice::ArithmeticOperator::DIVIDE: + op= "/"; + break; + case Dice::ArithmeticOperator::INTEGER_DIVIDE: + op= "|"; + break; + case Dice::ArithmeticOperator::POW: + op= "^"; + break; + } + if(wl) + { + return QString("%1 [label=\"ScalarOperatorNode %2\"]").arg(m_id, op); + } + else + { + return m_id; + } +} +qint64 ScalarOperatorNode::getPriority() const +{ + if((m_arithmeticOperator == Dice::ArithmeticOperator::PLUS) + || (m_arithmeticOperator == Dice::ArithmeticOperator::MINUS)) + { + return 1; + } + else if(m_arithmeticOperator == Dice::ArithmeticOperator::POW) + { + return 3; + } + else + { + return 2; + } +} +void ScalarOperatorNode::generateDotTree(QString& s) +{ + auto id= toString(true); + if(s.contains(id)) + return; + s.append(id); + s.append(";\n"); + + if(nullptr != m_nextNode) + { + s.append(toString(false)); + s.append(" -> "); + s.append(m_nextNode->toString(false)); + s.append("[label=\"nextNode\"];\n"); + m_nextNode->generateDotTree(s); + } + else + { + s.append(toString(false)); + s.append(" -> "); + s.append("nullptr"); + s.append(" [label=\"nextNode\"];\n"); + } + + if(nullptr != m_result) + { + s.append(toString(false)); + s.append(" ->"); + s.append(m_result->toString(false)); + s.append(" [label=\"Result\", style=\"dashed\"];\n"); + if(nullptr == m_nextNode) + m_result->generateDotTree(s); + } + QString str; + str.append("\n"); + if(nullptr != m_internalNode) + { + str.append(toString(false)); + str.append(" -> "); + str.append(m_internalNode->toString(false)); + str.append(" [label=\"internalNode\"];\n"); + m_internalNode->generateDotTree(str); + } + s.append(str); +} +QMap<Dice::ERROR_CODE, QString> ScalarOperatorNode::getExecutionErrorMap() +{ + if(nullptr != m_internalNode) + { + auto keys= m_internalNode->getExecutionErrorMap().keys(); + for(const auto& key : keys) + { + m_errors.insert(key, m_internalNode->getExecutionErrorMap().value(key)); + } + } + if(nullptr != m_nextNode) + { + auto keys= m_nextNode->getExecutionErrorMap().keys(); + for(auto const& key : keys) + { + m_errors.insert(key, m_nextNode->getExecutionErrorMap().value(key)); + } + } + return m_errors; +} +ExecutionNode* ScalarOperatorNode::getCopy() const +{ + ScalarOperatorNode* node= new ScalarOperatorNode(); + node->setInternalNode(m_internalNode->getCopy()); + node->setArithmeticOperator(m_arithmeticOperator); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/scalaroperatornode.h b/src/libparser/node/scalaroperatornode.h new file mode 100644 index 0000000..57a1049 --- /dev/null +++ b/src/libparser/node/scalaroperatornode.h @@ -0,0 +1,127 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef SCALAROPERATORNODE_H +#define SCALAROPERATORNODE_H + +#include <QChar> +#include <QMap> + +#include "die.h" +#include "executionnode.h" +#include "result/scalarresult.h" + +/** + * @brief The ScalarOperatorNode class + */ +class ScalarOperatorNode : public ExecutionNode +{ +public: + /** + * @brief The ArithmeticOperator enum + */ + // enum ArithmeticOperator {PLUS,MINUS,DIVIDE,MULTIPLICATION}; + /** + * @brief ScalarOperatorNode + */ + ScalarOperatorNode(); + /** + * @brief ~ScalarOperatorNode + */ + virtual ~ScalarOperatorNode(); + /** + * @brief run + */ + virtual void run(ExecutionNode*); + /** + * @brief setInternalNode + * @param node + */ + void setInternalNode(ExecutionNode* node); + /** + * @brief toString + * @param wl + * @return + */ + virtual QString toString(bool wl) const; + /** + * @brief getPriority + * @return + */ + virtual qint64 getPriority() const; + /** + * @brief generateDotTree + * @param s + */ + void generateDotTree(QString& s); + /** + * @brief getErrorList + * @return + */ + virtual QMap<Dice::ERROR_CODE, QString> getExecutionErrorMap(); + /** + * @brief getArithmeticOperator + * @return + */ + Dice::ArithmeticOperator getArithmeticOperator() const; + /** + * @brief setArithmeticOperator + * @param arithmeticOperator + */ + void setArithmeticOperator(const Dice::ArithmeticOperator& arithmeticOperator); + + /** + * @brief getCopy + * @return + */ + virtual ExecutionNode* getCopy() const; + +private: + /** + * @brief add + * @return + */ + static qint64 add(qreal, qreal); + /** + * @brief substract + * @return + */ + static qint64 substract(qreal, qreal); + /** + * @brief divide not static because of error management + * @return + */ + qreal divide(qreal, qreal); + /** + * @brief multiple + * @return + */ + static qint64 multiple(qreal, qreal); + + static qint64 pow(qreal a, qreal b); + +private: + ExecutionNode* m_internalNode; + ScalarResult* m_scalarResult; + Dice::ArithmeticOperator m_arithmeticOperator; +}; + +#endif // SCALAROPERATORNODE_H diff --git a/src/libparser/node/sortresult.cpp b/src/libparser/node/sortresult.cpp new file mode 100644 index 0000000..5d514cf --- /dev/null +++ b/src/libparser/node/sortresult.cpp @@ -0,0 +1,148 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "sortresult.h" + +#include "die.h" + +SortResultNode::SortResultNode() : m_diceResult(new DiceResult) +{ + m_ascending= true; + m_result= m_diceResult; +} +void SortResultNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr == previous) + { + return; + } + DiceResult* previousDiceResult= dynamic_cast<DiceResult*>(previous->getResult()); + m_diceResult->setPrevious(previousDiceResult); + if(nullptr == previousDiceResult) + return; + + auto const& diceList= previousDiceResult->getResultList(); + QList<Die*> diceList2= m_diceResult->getResultList(); + + /* const auto& asce = [](const Die* a,const Die* b){ + return a->getValue() < b->getValue(); + }; + const auto& desc = [](const Die* a,const Die* b){ + return a->getValue() > b->getValue(); + }; + + for(auto const dice : diceList) + { + Die* tmp1 = new Die(*dice); + diceList2.append(tmp1); + } + if(m_ascending) + std::sort(diceList2.begin(), diceList2.end(), asce); + else + std::sort(diceList2.begin(), diceList2.end(), desc);*/ + + // half-interval search sorting + for(int i= 0; i < diceList.size(); ++i) + { + Die* tmp1= new Die(*diceList[i]); + //qDebug() << tmp1->getColor() << diceList[i]->getColor(); + //*tmp1=*diceList[i]; + diceList[i]->displayed(); + + int j= 0; + bool found= false; + int start= 0; + int end= diceList2.size(); + Die* tmp2= nullptr; + while(!found) + { + int distance= end - start; + j= (start + end) / 2; + if(distance == 0) + { + j= end; + found= true; + } + else + { + tmp2= diceList2[j]; + if(tmp1->getValue() < tmp2->getValue()) + { + end= j; + } + else + { + start= j + 1; + } + } + } + diceList2.insert(j, tmp1); + } + + if(!m_ascending) + { + for(int i= 0; i < diceList2.size() / 2; ++i) + { + diceList2.swapItemsAt(i, diceList2.size() - (1 + i)); + } + } + m_diceResult->setResultList(diceList2); + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} +void SortResultNode::setSortAscending(bool asc) +{ + m_ascending= asc; +} +QString SortResultNode::toString(bool wl) const +{ + if(wl) + { + auto order= m_ascending ? QStringLiteral("Ascending") : QStringLiteral("Descending"); + return QString("%1 [label=\"SortResultNode %2\"]").arg(m_id, order); + } + else + { + return m_id; + } +} +qint64 SortResultNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_previousNode) + { + priority= m_previousNode->getPriority(); + } + return priority; +} +ExecutionNode* SortResultNode::getCopy() const +{ + SortResultNode* node= new SortResultNode(); + node->setSortAscending(m_ascending); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/sortresult.h b/src/libparser/node/sortresult.h new file mode 100644 index 0000000..f7510be --- /dev/null +++ b/src/libparser/node/sortresult.h @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef SORTRESULT_H +#define SORTRESULT_H + +#include "executionnode.h" +#include "result/diceresult.h" +/** + * @brief The SortResultNode class is an ExecutionNode, and it is dedicated to sort dice list. + * The sort is made by hand, using half-interval search algorithm. + */ +class SortResultNode : public ExecutionNode +{ +public: + /** + * @brief SortResultNode + */ + SortResultNode(); + /** + * @brief run + */ + virtual void run(ExecutionNode*); + + /** + * @brief setSortAscending + * @param asc + */ + void setSortAscending(bool asc); + /** + * @brief toString + * @return + */ + virtual QString toString(bool wl) const; + /** + * @brief getPriority + * @return + */ + virtual qint64 getPriority() const; + /** + * @brief getCopy + * @return + */ + virtual ExecutionNode* getCopy() const; + +private: + bool m_ascending; + DiceResult* m_diceResult; +}; + +#endif // SORTRESULT_H diff --git a/src/libparser/node/splitnode.cpp b/src/libparser/node/splitnode.cpp new file mode 100644 index 0000000..8faa0a5 --- /dev/null +++ b/src/libparser/node/splitnode.cpp @@ -0,0 +1,93 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "splitnode.h" + +SplitNode::SplitNode() : m_diceResult(new DiceResult()) +{ + m_result= m_diceResult; +} +void SplitNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr != previous) + { + m_result->setPrevious(previous->getResult()); + + Result* tmpResult= previous->getResult(); + if(nullptr != tmpResult) + { + DiceResult* dice= dynamic_cast<DiceResult*>(tmpResult); + if(nullptr != dice) + { + for(auto& oldDie : dice->getResultList()) + { + oldDie->displayed(); + m_diceResult->setOperator(oldDie->getOp()); + for(qint64& value : oldDie->getListValue()) + { + Die* tmpdie= new Die(); + tmpdie->insertRollValue(value); + tmpdie->setBase(oldDie->getBase()); + tmpdie->setMaxValue(oldDie->getMaxValue()); + tmpdie->setValue(value); + tmpdie->setOp(oldDie->getOp()); + m_diceResult->insertResult(tmpdie); + } + } + } + } + } + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} + +QString SplitNode::toString(bool withLabel) const +{ + if(withLabel) + { + return QString("%1 [label=\"SplitNode Node\"]").arg(m_id); + } + else + { + return m_id; + } +} +qint64 SplitNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_nextNode) + { + priority= m_nextNode->getPriority(); + } + return priority; +} +ExecutionNode* SplitNode::getCopy() const +{ + SplitNode* node= new SplitNode(); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/splitnode.h b/src/libparser/node/splitnode.h new file mode 100644 index 0000000..0ceeb00 --- /dev/null +++ b/src/libparser/node/splitnode.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef SPLITNODE_H +#define SPLITNODE_H + +#include "node/executionnode.h" +#include "result/diceresult.h" + +/** + * @brief The SplitNode class is an ExecutionNode. It is dedicated to split result of one dice into one dimension array. + */ +class SplitNode : public ExecutionNode +{ +public: + SplitNode(); + void run(ExecutionNode* previous); + virtual QString toString(bool withLabel) const; + virtual qint64 getPriority() const; + virtual ExecutionNode* getCopy() const; + +private: + DiceResult* m_diceResult; +}; + +#endif // NUMBERNODE_H diff --git a/src/libparser/node/startingnode.cpp b/src/libparser/node/startingnode.cpp new file mode 100644 index 0000000..97248c6 --- /dev/null +++ b/src/libparser/node/startingnode.cpp @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (C) 2015 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "startingnode.h" +#include <QDebug> + +StartingNode::StartingNode() {} +void StartingNode::run(ExecutionNode*) +{ + m_previousNode= nullptr; + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} +QString StartingNode::toString(bool withlabel) const +{ + if(withlabel) + { + return QString("%1 [label=\"StartingNode\"]").arg(m_id); + } + else + { + return m_id; + } +} + +qint64 StartingNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_nextNode) + { + priority= m_nextNode->getPriority(); + } + return priority; +} +ExecutionNode* StartingNode::getCopy() const +{ + StartingNode* node= new StartingNode(); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/startingnode.h b/src/libparser/node/startingnode.h new file mode 100644 index 0000000..eea72a9 --- /dev/null +++ b/src/libparser/node/startingnode.h @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (C) 2015 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * rolisteam is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef STARTINGNODE_H +#define STARTINGNODE_H + +#include "executionnode.h" + +/** + * @brief The StartingNode class is an ExecutionNode, StartingNode is dedicated to be the first node + * in the execution tree. + */ +class StartingNode : public ExecutionNode +{ +public: + /** + * @brief StartingNode + */ + StartingNode(); + /** + * @brief run + */ + virtual void run(ExecutionNode*); + /** + * @brief toString + * @return + */ + virtual QString toString(bool withlabel) const; + /** + * @brief getPriority + * @return + */ + virtual qint64 getPriority() const; + /** + * @brief getCopy + * @return + */ + virtual ExecutionNode* getCopy() const; +}; + +#endif // STARTINGNODE_H diff --git a/src/libparser/node/stringnode.cpp b/src/libparser/node/stringnode.cpp new file mode 100644 index 0000000..e908463 --- /dev/null +++ b/src/libparser/node/stringnode.cpp @@ -0,0 +1,58 @@ +#include "stringnode.h" + +StringNode::StringNode() : m_stringResult(new StringResult()) +{ + m_result= m_stringResult; +} + +void StringNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr != previous) + { + m_result->setPrevious(previous->getResult()); + } + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} + +void StringNode::setString(QString str) +{ + m_data= str; + m_stringResult->addText(m_data); + m_stringResult->finished(); +} +QString StringNode::toString(bool withLabel) const +{ + if(withLabel) + { + QString dataCopy= m_data; + + return QString("%1 [label=\"StringNode %2\"]").arg(m_id, dataCopy.replace('%', '\\')); + } + else + { + return m_id; + } +} +qint64 StringNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_nextNode) + { + priority= m_nextNode->getPriority(); + } + return priority; +} +ExecutionNode* StringNode::getCopy() const +{ + StringNode* node= new StringNode(); + node->setString(m_data); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/stringnode.h b/src/libparser/node/stringnode.h new file mode 100644 index 0000000..4079b7f --- /dev/null +++ b/src/libparser/node/stringnode.h @@ -0,0 +1,29 @@ +#ifndef STRINGNODE_H +#define STRINGNODE_H + +#include "node/executionnode.h" +#include "result/stringresult.h" + +/** + * @brief The StringNode class is an ExecutionNode. It is dedicated to store string and display result. + */ +class StringNode : public ExecutionNode +{ +public: + StringNode(); + void run(ExecutionNode* previous); + void setString(QString str); + virtual QString toString(bool withLabel) const; + virtual qint64 getPriority() const; + /** + * @brief getCopy + * @return + */ + virtual ExecutionNode* getCopy() const; + +private: + QString m_data; + StringResult* m_stringResult; +}; + +#endif // STRINGNODE_H diff --git a/src/libparser/node/switchcasenode.cpp b/src/libparser/node/switchcasenode.cpp new file mode 100644 index 0000000..880fa4d --- /dev/null +++ b/src/libparser/node/switchcasenode.cpp @@ -0,0 +1,149 @@ +/*************************************************************************** + * Copyright (C) 2021 by Renaud Guezennec * + * http://www.rolisteam.org/contact * + * * + * This software is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "switchcasenode.h" + +#include "stringresult.h" +#include <QDebug> +#include <diceparser/parsingtoolbox.h> + +SwitchCaseNode::SwitchCaseNode() : m_stringResult(new StringResult) +{ + m_result= m_stringResult; +} + +void SwitchCaseNode::setStopAtFirt(bool b) +{ + m_stopAtFirst= b; +} + +void SwitchCaseNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr == previous) + { + m_errors.insert(Dice::ERROR_CODE::NO_PREVIOUS_ERROR, + QStringLiteral("No previous node before Switch/Case operator")); + return; + } + auto previousResult= previous->getResult(); + m_result->setPrevious(previousResult); + + if(nullptr == previousResult + || (!previousResult->hasResultOfType(Dice::RESULT_TYPE::SCALAR) + && !previousResult->hasResultOfType(Dice::RESULT_TYPE::DICE_LIST))) + { + m_errors.insert(Dice::ERROR_CODE::NO_VALID_RESULT, + QStringLiteral("No scalar or dice result before Switch/Case operator")); + return; + } + + auto diceResult= dynamic_cast<DiceResult*>(previousResult); + + QSet<QString> alreadyValidDice; + QStringList finalResultList; + if(diceResult) + { + for(auto die : diceResult->getResultList()) + { + QStringList resultList; + for(auto const& info : qAsConst(m_branchList)) + { + if(m_stopAtFirst && !resultList.isEmpty()) + break; + if(info->validatorList) + { + if(info->validatorList->hasValid(die, true)) + { + auto lastNode= ParsingToolBox::getLeafNode(info->node); + if(lastNode && lastNode->getResult()) + { + resultList << lastNode->getResult()->getStringResult(); + } + } + } + else if(resultList.isEmpty()) + { + info->node->run(m_previousNode); + auto lastNode= ParsingToolBox::getLeafNode(info->node); + if(lastNode && lastNode->getResult()) + { + resultList << lastNode->getResult()->getStringResult(); + } + else + resultList << QString(); + } + } + finalResultList << resultList; + } + } + for(auto const& str : qAsConst(finalResultList)) + m_stringResult->addText(str); + + if(m_stringResult->getText().isEmpty()) + m_errors.insert(Dice::ERROR_CODE::NO_VALID_RESULT, QStringLiteral("No value fits the Switch/Case operator")); + + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} + +QString SwitchCaseNode::toString(bool withLabel) const +{ + if(withLabel) + { + return QString("%1 [label=\"SwitchCaseNode\"]").arg(m_id); + } + else + { + return m_id; + } +} + +qint64 SwitchCaseNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_previousNode) + { + priority= m_previousNode->getPriority(); + } + return priority; +} + +ExecutionNode* SwitchCaseNode::getCopy() const +{ + SwitchCaseNode* node= new SwitchCaseNode(); + for(auto const& info : qAsConst(m_branchList)) + { + node->insertCase(info->node, info->validatorList); + } + + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} + +void SwitchCaseNode::insertCase(ExecutionNode* node, ValidatorList* validator) +{ + std::unique_ptr<Dice::CaseInfo> info(new Dice::CaseInfo{validator, node}); + m_branchList.push_back(std::move(info)); +} diff --git a/src/libparser/node/switchcasenode.h b/src/libparser/node/switchcasenode.h new file mode 100644 index 0000000..a0f658d --- /dev/null +++ b/src/libparser/node/switchcasenode.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2021 by Renaud Guezennec * + * http://www.rolisteam.org/contact * + * * + * This software is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef SWITCHCASENODE_H +#define SWITCHCASENODE_H + +#include <memory> +#include <vector> + +#include "executionnode.h" +#include "validatorlist.h" + +class StringResult; +class SwitchCaseNode : public ExecutionNode +{ +public: + SwitchCaseNode(); + void setStopAtFirt(bool b); + + void run(ExecutionNode* previous= nullptr) override; + + QString toString(bool withLabel) const override; + qint64 getPriority() const override; + ExecutionNode* getCopy() const override; + + void insertCase(ExecutionNode* node, ValidatorList* validator); + +private: + std::vector<std::unique_ptr<Dice::CaseInfo>> m_branchList; + StringResult* m_stringResult; + bool m_stopAtFirst= false; +}; + +#endif // SWITCHCASENODE_H diff --git a/src/libparser/node/uniquenode.cpp b/src/libparser/node/uniquenode.cpp new file mode 100644 index 0000000..c4668be --- /dev/null +++ b/src/libparser/node/uniquenode.cpp @@ -0,0 +1,93 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "uniquenode.h" + +UniqueNode::UniqueNode() : m_diceResult(new DiceResult()) +{ + m_result= m_diceResult; +} +void UniqueNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if(nullptr != previous) + { + m_result->setPrevious(previous->getResult()); + Result* tmpResult= previous->getResult(); + if(nullptr != tmpResult) + { + DiceResult* dice= dynamic_cast<DiceResult*>(tmpResult); + if(nullptr != dice) + { + auto const& resultList= dice->getResultList(); + std::vector<qint64> formerValues; + formerValues.reserve(resultList.size()); + for(auto& oldDie : resultList) + { + auto value= oldDie->getValue(); + auto it= std::find(formerValues.begin(), formerValues.end(), value); + + if(it == formerValues.end()) + { + auto die= new Die(*oldDie); + m_diceResult->insertResult(die); + formerValues.push_back(value); + } + oldDie->displayed(); + } + } + } + } + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} + +QString UniqueNode::toString(bool withLabel) const +{ + if(withLabel) + { + return QString("%1 [label=\"UniqueNode Node\"]").arg(m_id); + } + else + { + return m_id; + } +} +qint64 UniqueNode::getPriority() const +{ + qint64 priority= 0; + if(nullptr != m_nextNode) + { + priority= m_nextNode->getPriority(); + } + return priority; +} +ExecutionNode* UniqueNode::getCopy() const +{ + UniqueNode* node= new UniqueNode(); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} diff --git a/src/libparser/node/uniquenode.h b/src/libparser/node/uniquenode.h new file mode 100644 index 0000000..039ba11 --- /dev/null +++ b/src/libparser/node/uniquenode.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * https://rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef UNIQUENODE_H +#define UNIQUENODE_H + +#include "node/executionnode.h" +#include "result/diceresult.h" + +/** + * @brief The UniqueNode class is an ExecutionNode. It is dedicated to unique result of one dice into one dimension array. + */ +class UniqueNode : public ExecutionNode +{ +public: + UniqueNode(); + void run(ExecutionNode* previous); + virtual QString toString(bool withLabel) const; + virtual qint64 getPriority() const; + virtual ExecutionNode* getCopy() const; + +private: + DiceResult* m_diceResult; +}; + +#endif // NUMBERNODE_H diff --git a/src/libparser/node/valueslistnode.cpp b/src/libparser/node/valueslistnode.cpp new file mode 100644 index 0000000..33a347d --- /dev/null +++ b/src/libparser/node/valueslistnode.cpp @@ -0,0 +1,62 @@ +#include "valueslistnode.h" + +#include "variablenode.h" + +ValuesListNode::ValuesListNode() : m_diceResult(new DiceResult()) +{ + m_result= m_diceResult; +} + +void ValuesListNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + for(auto node : m_data) + { + node->run(this); + auto result= node->getResult(); + if(!result) + continue; + auto val= result->getResult(Dice::RESULT_TYPE::SCALAR).toInt(); + Die* die= new Die(); + auto dyna= dynamic_cast<VariableNode*>(node); + if(nullptr != dyna) + dyna->setDisplayed(); + die->insertRollValue(val); + m_diceResult->insertResult(die); + } + + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } +} + +void ValuesListNode::insertValue(ExecutionNode* value) +{ + m_data.push_back(value); +} +ExecutionNode* ValuesListNode::getCopy() const +{ + ValuesListNode* node= new ValuesListNode(); + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} +QString ValuesListNode::toString(bool wl) const +{ + if(wl) + { + return QString("%1 [label=\"ValuesListNode list:\"]").arg(m_id); + } + else + { + return m_id; + } +} +qint64 ValuesListNode::getPriority() const +{ + qint64 priority= 4; + return priority; +} diff --git a/src/libparser/node/valueslistnode.h b/src/libparser/node/valueslistnode.h new file mode 100644 index 0000000..100f275 --- /dev/null +++ b/src/libparser/node/valueslistnode.h @@ -0,0 +1,24 @@ +#ifndef VALUESLISTNODE_H +#define VALUESLISTNODE_H + +#include "executionnode.h" +#include "result/diceresult.h" + +class ValuesListNode : public ExecutionNode +{ +public: + ValuesListNode(); + + virtual void run(ExecutionNode* previous= nullptr) override; + virtual QString toString(bool) const override; + virtual qint64 getPriority() const override; + virtual ExecutionNode* getCopy() const override; + + void insertValue(ExecutionNode*); + +private: + std::vector<ExecutionNode*> m_data; + DiceResult* m_diceResult = nullptr; +}; + +#endif // VALUESLISTNODE_H diff --git a/src/libparser/node/variablenode.cpp b/src/libparser/node/variablenode.cpp new file mode 100644 index 0000000..709ab46 --- /dev/null +++ b/src/libparser/node/variablenode.cpp @@ -0,0 +1,112 @@ +#include "variablenode.h" + +#include "diceresult.h" +#include <diceparser/parsingtoolbox.h> + +VariableNode::VariableNode() {} + +void VariableNode::run(ExecutionNode* previous) +{ + m_previousNode= previous; + if((nullptr != m_data) && (m_data->size() > m_index)) + { + auto value= (*m_data)[m_index]; + value= ParsingToolBox::getLeafNode(value); + if(nullptr == value) + return; + + auto result= value->getResult(); + if(!result) + return; + + m_result= result->getCopy(); + auto diceResult= dynamic_cast<DiceResult*>(result); + if(nullptr != diceResult) + { + for(auto& die : diceResult->getResultList()) + { + die->setDisplayed(false); + } + } + + if(nullptr != m_nextNode) + { + m_nextNode->run(this); + } + } + else + { + m_errors.insert(Dice::ERROR_CODE::NO_VARIBALE, QObject::tr("No variable at index:%1").arg(m_index + 1)); + } +} + +void VariableNode::setDisplayed() +{ + if(!m_result) + return; + auto diceResult= dynamic_cast<DiceResult*>(m_result); + if(nullptr == diceResult) + return; + + for(auto& die : diceResult->getResultList()) + { + die->setDisplayed(true); + } +} + +QString VariableNode::toString(bool withLabel) const +{ + if(withLabel) + { + return QString("%1 [label=\"VariableNode index: %2\"]").arg(m_id).arg(m_index + 1); + } + else + { + return m_id; + } +} + +qint64 VariableNode::getPriority() const +{ + qint64 priority= 4; + if(nullptr != m_previousNode) + { + priority= m_previousNode->getPriority(); + } + return priority; +} + +ExecutionNode* VariableNode::getCopy() const +{ + VariableNode* node= new VariableNode(); + node->setIndex(m_index); + if(nullptr != m_data) + { + node->setData(m_data); + } + if(nullptr != m_nextNode) + { + node->setNextNode(m_nextNode->getCopy()); + } + return node; +} + +quint64 VariableNode::getIndex() const +{ + return m_index; +} + +void VariableNode::setIndex(quint64 index) +{ + m_index= index; +} + +std::vector<ExecutionNode*>* VariableNode::getData() const +{ + return m_data; +} + +void VariableNode::setData(std::vector<ExecutionNode*>* data) +{ + m_data= data; +} diff --git a/src/libparser/node/variablenode.h b/src/libparser/node/variablenode.h new file mode 100644 index 0000000..8bf1cb1 --- /dev/null +++ b/src/libparser/node/variablenode.h @@ -0,0 +1,35 @@ +#ifndef VARIABLENODE_H +#define VARIABLENODE_H + +#include "node/executionnode.h" + +/** + * @brief The VariableNode class is an ExecutionNode. It is dedicated to retrive + * variable value from other starting node. + */ +class VariableNode : public ExecutionNode +{ +public: + VariableNode(); + void run(ExecutionNode* previous) override; + virtual QString toString(bool withLabel) const override; + virtual qint64 getPriority() const override; + /** + * @brief getCopy + * @return + */ + virtual ExecutionNode* getCopy() const override; + quint64 getIndex() const; + void setIndex(quint64 index); + + std::vector<ExecutionNode*>* getData() const; + void setData(std::vector<ExecutionNode*>* data); + + void setDisplayed(); + +private: + quint64 m_index; + std::vector<ExecutionNode*>* m_data= nullptr; +}; + +#endif // VARIABLENODE_H |