File indexing completed on 2024-05-12 05:39:28

0001 /***************************************************************************
0002  * Copyright (C) 2014 by Renaud Guezennec                                   *
0003  * https://rolisteam.org/contact                      *
0004  *                                                                          *
0005  *  This file is part of DiceParser                                         *
0006  *                                                                          *
0007  * DiceParser is free software; you can redistribute it and/or modify       *
0008  * it under the terms of the GNU General Public License as published by     *
0009  * the Free Software Foundation; either version 2 of the License, or        *
0010  * (at your option) any later version.                                      *
0011  *                                                                          *
0012  * This program is distributed in the hope that it will be useful,          *
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of           *
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the             *
0015  * GNU General Public License for more details.                             *
0016  *                                                                          *
0017  * You should have received a copy of the GNU General Public License        *
0018  * along with this program; if not, write to the                            *
0019  * Free Software Foundation, Inc.,                                          *
0020  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.                 *
0021  ***************************************************************************/
0022 #include "scalaroperatornode.h"
0023 
0024 #include "result/diceresult.h"
0025 #include <QDebug>
0026 
0027 ScalarOperatorNode::ScalarOperatorNode()
0028     : m_internalNode(nullptr), m_scalarResult(new ScalarResult()), m_arithmeticOperator(Dice::ArithmeticOperator::PLUS)
0029 {
0030     m_result= m_scalarResult;
0031 }
0032 ScalarOperatorNode::~ScalarOperatorNode()
0033 {
0034     if(nullptr != m_internalNode)
0035     {
0036         delete m_internalNode;
0037         m_internalNode= nullptr;
0038     }
0039 }
0040 
0041 void ScalarOperatorNode::run(ExecutionNode* previous)
0042 {
0043     m_previousNode= previous;
0044     if(nullptr != m_internalNode)
0045     {
0046         m_internalNode->run(this);
0047     }
0048     if(nullptr != previous)
0049     {
0050         auto previousResult= previous->getResult();
0051 
0052         if(nullptr != previousResult)
0053         {
0054             ExecutionNode* internal= m_internalNode;
0055             if(nullptr != internal)
0056             {
0057                 while(nullptr != internal->getNextNode())
0058                 {
0059                     internal= internal->getNextNode();
0060                 }
0061 
0062                 Result* internalResult= internal->getResult();
0063                 m_result->setPrevious(internalResult);
0064                 if(nullptr != m_internalNode->getResult())
0065                 {
0066                     m_internalNode->getResult()->setPrevious(previousResult);
0067                 }
0068 
0069                 if(internalResult == nullptr)
0070                 {
0071                     m_errors.insert(Dice::ERROR_CODE::NO_VALID_RESULT,
0072                                     QObject::tr("No Valid result in arithmetic operation: %1").arg(toString(true)));
0073                     return;
0074                 }
0075 
0076                 switch(m_arithmeticOperator)
0077                 {
0078                 case Dice::ArithmeticOperator::PLUS:
0079                     m_scalarResult->setValue(add(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(),
0080                                                  internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal()));
0081                     break;
0082                 case Dice::ArithmeticOperator::MINUS:
0083                     m_scalarResult->setValue(substract(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(),
0084                                                        internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal()));
0085                     break;
0086                 case Dice::ArithmeticOperator::MULTIPLICATION:
0087                     m_scalarResult->setValue(multiple(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(),
0088                                                       internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal()));
0089                     break;
0090                 case Dice::ArithmeticOperator::DIVIDE:
0091                     m_scalarResult->setValue(divide(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(),
0092                                                     internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal()));
0093                     break;
0094                 case Dice::ArithmeticOperator::INTEGER_DIVIDE:
0095                     m_scalarResult->setValue(
0096                         static_cast<int>(divide(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(),
0097                                                 internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal())));
0098                     break;
0099                 case Dice::ArithmeticOperator::POW:
0100                     m_scalarResult->setValue(pow(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(),
0101                                                  internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal()));
0102                     break;
0103                 }
0104             }
0105 
0106             if(nullptr != m_nextNode)
0107             {
0108                 m_nextNode->run(this);
0109             }
0110         }
0111     }
0112 }
0113 /*bool ScalarOperatorNode::setOperatorChar(QChar c)
0114 {
0115     if(m_scalarOperationList.contains(c))
0116     {
0117         m_operator = m_scalarOperationList.value(c);
0118         return true;
0119     }
0120     return false;
0121 }*/
0122 
0123 void ScalarOperatorNode::setInternalNode(ExecutionNode* node)
0124 {
0125     m_internalNode= node;
0126 }
0127 qint64 ScalarOperatorNode::add(qreal a, qreal b)
0128 {
0129     return static_cast<qint64>(a + b);
0130 }
0131 qint64 ScalarOperatorNode::substract(qreal a, qreal b)
0132 {
0133     return static_cast<qint64>(a - b);
0134 }
0135 qreal ScalarOperatorNode::divide(qreal a, qreal b)
0136 {
0137     if(qFuzzyCompare(b, 0))
0138     {
0139         m_errors.insert(Dice::ERROR_CODE::DIVIDE_BY_ZERO, QObject::tr("Division by zero"));
0140         return 0;
0141     }
0142     return static_cast<qreal>(a / b);
0143 }
0144 qint64 ScalarOperatorNode::multiple(qreal a, qreal b)
0145 {
0146     return static_cast<qint64>(a * b);
0147 }
0148 qint64 ScalarOperatorNode::pow(qreal a, qreal b)
0149 {
0150     return static_cast<qint64>(std::pow(a, b));
0151 }
0152 Dice::ArithmeticOperator ScalarOperatorNode::getArithmeticOperator() const
0153 {
0154     return m_arithmeticOperator;
0155 }
0156 
0157 void ScalarOperatorNode::setArithmeticOperator(const Dice::ArithmeticOperator& arithmeticOperator)
0158 {
0159     m_arithmeticOperator= arithmeticOperator;
0160 }
0161 
0162 QString ScalarOperatorNode::toString(bool wl) const
0163 {
0164     QString op= "";
0165     switch(m_arithmeticOperator)
0166     {
0167     case Dice::ArithmeticOperator::PLUS:
0168         op= "+";
0169         break;
0170     case Dice::ArithmeticOperator::MINUS:
0171         op= "-";
0172         break;
0173     case Dice::ArithmeticOperator::MULTIPLICATION:
0174         op= "*";
0175         break;
0176     case Dice::ArithmeticOperator::DIVIDE:
0177         op= "/";
0178         break;
0179     case Dice::ArithmeticOperator::INTEGER_DIVIDE:
0180         op= "|";
0181         break;
0182     case Dice::ArithmeticOperator::POW:
0183         op= "^";
0184         break;
0185     }
0186     if(wl)
0187     {
0188         return QString("%1 [label=\"ScalarOperatorNode %2\"]").arg(m_id, op);
0189     }
0190     else
0191     {
0192         return m_id;
0193     }
0194 }
0195 qint64 ScalarOperatorNode::getPriority() const
0196 {
0197     if((m_arithmeticOperator == Dice::ArithmeticOperator::PLUS)
0198        || (m_arithmeticOperator == Dice::ArithmeticOperator::MINUS))
0199     {
0200         return 1;
0201     }
0202     else if(m_arithmeticOperator == Dice::ArithmeticOperator::POW)
0203     {
0204         return 3;
0205     }
0206     else
0207     {
0208         return 2;
0209     }
0210 }
0211 void ScalarOperatorNode::generateDotTree(QString& s)
0212 {
0213     auto id= toString(true);
0214     if(s.contains(id))
0215         return;
0216     s.append(id);
0217     s.append(";\n");
0218 
0219     if(nullptr != m_nextNode)
0220     {
0221         s.append(toString(false));
0222         s.append(" -> ");
0223         s.append(m_nextNode->toString(false));
0224         s.append("[label=\"nextNode\"];\n");
0225         m_nextNode->generateDotTree(s);
0226     }
0227     else
0228     {
0229         s.append(toString(false));
0230         s.append(" -> ");
0231         s.append("nullptr");
0232         s.append(" [label=\"nextNode\"];\n");
0233     }
0234 
0235     if(nullptr != m_result)
0236     {
0237         s.append(toString(false));
0238         s.append(" ->");
0239         s.append(m_result->toString(false));
0240         s.append(" [label=\"Result\", style=\"dashed\"];\n");
0241         if(nullptr == m_nextNode)
0242             m_result->generateDotTree(s);
0243     }
0244     QString str;
0245     str.append("\n");
0246     if(nullptr != m_internalNode)
0247     {
0248         str.append(toString(false));
0249         str.append(" -> ");
0250         str.append(m_internalNode->toString(false));
0251         str.append(" [label=\"internalNode\"];\n");
0252         m_internalNode->generateDotTree(str);
0253     }
0254     s.append(str);
0255 }
0256 QMap<Dice::ERROR_CODE, QString> ScalarOperatorNode::getExecutionErrorMap()
0257 {
0258     if(nullptr != m_internalNode)
0259     {
0260         auto keys= m_internalNode->getExecutionErrorMap().keys();
0261         for(const auto& key : keys)
0262         {
0263             m_errors.insert(key, m_internalNode->getExecutionErrorMap().value(key));
0264         }
0265     }
0266     if(nullptr != m_nextNode)
0267     {
0268         auto keys= m_nextNode->getExecutionErrorMap().keys();
0269         for(auto const& key : keys)
0270         {
0271             m_errors.insert(key, m_nextNode->getExecutionErrorMap().value(key));
0272         }
0273     }
0274     return m_errors;
0275 }
0276 ExecutionNode* ScalarOperatorNode::getCopy() const
0277 {
0278     ScalarOperatorNode* node= new ScalarOperatorNode();
0279     node->setInternalNode(m_internalNode->getCopy());
0280     node->setArithmeticOperator(m_arithmeticOperator);
0281     if(nullptr != m_nextNode)
0282     {
0283         node->setNextNode(m_nextNode->getCopy());
0284     }
0285     return node;
0286 }