File indexing completed on 2024-04-28 05:37:02

0001 /***************************************************************************
0002  * Copyright (C) 2014 by Renaud Guezennec                                   *
0003  * http://www.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 "validatorlist.h"
0023 
0024 #include "result/diceresult.h"
0025 #include "result/result.h"
0026 #include "validator.h"
0027 #include <QDebug>
0028 #include <utility>
0029 
0030 void mergeResultsAsAND(const ValidatorResult& diceList, ValidatorResult& result)
0031 {
0032     ValidatorResult val;
0033     for(auto dice : diceList.validDice())
0034     {
0035         if(result.contains(dice.first) || diceList.allTrue())
0036             val.appendValidDice(dice.first, dice.second);
0037     }
0038     result= val;
0039     result.setAllTrue(diceList.allTrue() & result.allTrue());
0040 }
0041 
0042 void mergeResultsAsExeclusiveOR(const ValidatorResult& diceList, ValidatorResult& result)
0043 {
0044     ValidatorResult val;
0045     for(auto dice : diceList.validDice())
0046     {
0047         if(!result.contains(dice.first))
0048             val.appendValidDice(dice.first, dice.second);
0049     }
0050     result= val;
0051     result.setAllTrue(diceList.allTrue() ^ result.allTrue());
0052 }
0053 
0054 DiceResult* getDiceResult(Result* result)
0055 {
0056     auto dice= dynamic_cast<DiceResult*>(result);
0057     if(nullptr == dice)
0058     {
0059         auto value= result->getResult(Dice::RESULT_TYPE::SCALAR).toInt();
0060         dice= new DiceResult();
0061         auto die= new Die();
0062         die->setValue(value);
0063         dice->insertResult(die);
0064         qWarning("Error, no dice result");
0065         // TODO: manage error here.
0066     }
0067     return dice;
0068 }
0069 
0070 //////////////////////////////////
0071 /// \brief ValidatorResult::ValidatorResult
0072 ///
0073 ///
0074 ///
0075 /// ////////////////////////////////
0076 ValidatorResult::ValidatorResult() {}
0077 
0078 const std::vector<std::pair<Die*, qint64>>& ValidatorResult::validDice() const
0079 {
0080     return m_validDice;
0081 }
0082 
0083 std::vector<std::pair<Die*, qint64>>& ValidatorResult::validDiceRef()
0084 {
0085     return m_validDice;
0086 }
0087 
0088 void ValidatorResult::appendValidDice(Die* die, qint64 sum)
0089 {
0090     m_validDice.push_back(std::make_pair(die, sum));
0091 }
0092 
0093 void ValidatorResult::setAllTrue(bool allTrue)
0094 {
0095     m_allTrue= allTrue;
0096 }
0097 
0098 bool ValidatorResult::allTrue() const
0099 {
0100     return m_allTrue;
0101 }
0102 
0103 bool ValidatorResult::contains(Die* die)
0104 {
0105     auto it= std::find_if(m_validDice.begin(), m_validDice.end(),
0106                           [die](const std::pair<Die*, qint64>& pair) { return pair.first == die; });
0107 
0108     return it != m_validDice.end();
0109 }
0110 
0111 ////////////////////////////////////
0112 /// \brief ValidatorList::ValidatorList
0113 ///***
0114 ///
0115 ////////////////////////////////////
0116 
0117 ValidatorList::ValidatorList() {}
0118 
0119 ValidatorList::~ValidatorList()
0120 {
0121     qDeleteAll(m_validatorList);
0122 }
0123 qint64 ValidatorList::hasValid(Die* b, bool recursive, bool unhighlight) const
0124 {
0125     int i= 0;
0126     qint64 sum= 0;
0127     bool highLight= false;
0128     for(auto& validator : m_validatorList)
0129     {
0130         qint64 val= validator->hasValid(b, recursive, unhighlight);
0131         if(i == 0)
0132         {
0133             sum= val;
0134             if(b->isHighlighted())
0135             {
0136                 highLight= b->isHighlighted();
0137             }
0138         }
0139         else
0140         {
0141             switch(m_operators.at(i - 1))
0142             {
0143             case Dice::LogicOperation::OR:
0144                 sum|= val;
0145 
0146                 if(highLight)
0147                 {
0148                     b->setHighlighted(highLight);
0149                 }
0150                 break;
0151             case Dice::LogicOperation::EXCLUSIVE_OR:
0152                 sum^= val; /// @todo may required to be done by hand
0153                 break;
0154             case Dice::LogicOperation::AND:
0155                 sum&= val;
0156                 break;
0157             default:
0158                 break;
0159             }
0160         }
0161         ++i;
0162     }
0163 
0164     return sum;
0165 }
0166 
0167 QString ValidatorList::toString()
0168 {
0169     QString str= "";
0170     /*switch (m_operator)
0171     {
0172     case Equal:
0173         str.append("=");
0174         break;
0175     case GreaterThan:
0176         str.append(">");
0177         break;
0178     case LesserThan:
0179         str.append("<");
0180         break;
0181     case GreaterOrEqual:
0182         str.append(">=");
0183         break;
0184     case LesserOrEqual:
0185         str.append("<=");
0186         break;
0187     }
0188     return QString("[%1%2]").arg(str).arg(m_value);*/
0189     return str;
0190 }
0191 namespace
0192 {
0193 Dice::CONDITION_STATE testAND(Dice::CONDITION_STATE before, Dice::CONDITION_STATE current)
0194 {
0195     if(before == Dice::CONDITION_STATE::UNREACHABLE || current == Dice::CONDITION_STATE::UNREACHABLE)
0196         return Dice::CONDITION_STATE::UNREACHABLE;
0197     else if(before == Dice::CONDITION_STATE::ALWAYSTRUE && current == Dice::CONDITION_STATE::ALWAYSTRUE)
0198         return Dice::CONDITION_STATE::ALWAYSTRUE;
0199     else
0200         return Dice::CONDITION_STATE::REACHABLE;
0201 }
0202 
0203 Dice::CONDITION_STATE testOR(Dice::CONDITION_STATE before, Dice::CONDITION_STATE current)
0204 {
0205     if(before == Dice::CONDITION_STATE::UNREACHABLE && current == Dice::CONDITION_STATE::UNREACHABLE)
0206         return Dice::CONDITION_STATE::UNREACHABLE;
0207     else if(before == Dice::CONDITION_STATE::ALWAYSTRUE || current == Dice::CONDITION_STATE::ALWAYSTRUE)
0208         return Dice::CONDITION_STATE::ALWAYSTRUE;
0209     else
0210         return Dice::CONDITION_STATE::REACHABLE;
0211 }
0212 
0213 Dice::CONDITION_STATE testXOR(Dice::CONDITION_STATE before, Dice::CONDITION_STATE current)
0214 {
0215     if(before == current
0216        && (before == Dice::CONDITION_STATE::UNREACHABLE || before == Dice::CONDITION_STATE::ALWAYSTRUE))
0217         return Dice::CONDITION_STATE::UNREACHABLE;
0218     else if((before != current)
0219             && (before == Dice::CONDITION_STATE::ALWAYSTRUE || before == Dice::CONDITION_STATE::UNREACHABLE)
0220             && (before != Dice::CONDITION_STATE::REACHABLE || current != Dice::CONDITION_STATE::REACHABLE))
0221         return Dice::CONDITION_STATE::ALWAYSTRUE;
0222     else
0223         return Dice::CONDITION_STATE::REACHABLE;
0224 }
0225 } // namespace
0226 
0227 Dice::CONDITION_STATE ValidatorList::isValidRangeSize(const std::pair<qint64, qint64>& range) const
0228 {
0229     std::vector<Dice::CONDITION_STATE> vec;
0230     std::transform(m_validatorList.begin(), m_validatorList.end(), std::back_inserter(vec),
0231                    [range](Validator* validator) -> Dice::CONDITION_STATE
0232                    { return validator->isValidRangeSize(range); });
0233 
0234     auto itError= std::find(vec.begin(), vec.end(), Dice::CONDITION_STATE::ERROR_STATE);
0235 
0236     if(vec.size() == 1)
0237         return vec.front();
0238 
0239     if((static_cast<int>(vec.size()) != m_operators.size() + 1) || (itError != vec.end()))
0240     {
0241         return Dice::CONDITION_STATE::ERROR_STATE;
0242     }
0243 
0244     std::size_t i= 0;
0245     Dice::CONDITION_STATE val= Dice::CONDITION_STATE::ERROR_STATE;
0246     for(const auto& op : m_operators)
0247     {
0248         auto currentState= vec[i + 1];
0249         if(i == 0)
0250         {
0251             val= vec[i];
0252         }
0253         switch(op)
0254         {
0255         case Dice::LogicOperation::OR:
0256             val= testAND(val, currentState);
0257             break;
0258         case Dice::LogicOperation::EXCLUSIVE_OR:
0259             val= testOR(val, currentState);
0260             break;
0261         case Dice::LogicOperation::AND:
0262             val= testXOR(val, currentState);
0263             break;
0264         case Dice::LogicOperation::NONE:
0265             val= Dice::CONDITION_STATE::ERROR_STATE;
0266             break;
0267         }
0268 
0269         ++i;
0270     }
0271     return val;
0272 }
0273 
0274 void ValidatorList::setOperationList(const QVector<Dice::LogicOperation>& m)
0275 {
0276     m_operators= m;
0277 }
0278 
0279 void ValidatorList::setValidators(const QList<Validator*>& valids)
0280 {
0281     qDeleteAll(m_validatorList);
0282     m_validatorList= valids;
0283 }
0284 
0285 void ValidatorList::validResult(Result* result, bool recursive, bool unlight,
0286                                 std::function<void(Die*, qint64)> functor) const
0287 {
0288     std::vector<ValidatorResult> validityData;
0289     for(auto& validator : m_validatorList)
0290     {
0291         ValidatorResult validResult;
0292         switch(validator->getConditionType())
0293         {
0294         case Dice::OnScalar:
0295         {
0296             Die die;
0297             auto scalar= result->getResult(Dice::RESULT_TYPE::SCALAR).toInt();
0298             die.insertRollValue(scalar);
0299             if(validator->hasValid(&die, recursive, unlight))
0300             {
0301                 validResult.setAllTrue(true);
0302                 DiceResult* diceResult= getDiceResult(result);
0303                 if(nullptr == diceResult)
0304                     break;
0305 
0306                 if(m_validatorList.size() > 1)
0307                 {
0308                     for(auto const& die : qAsConst(diceResult->getResultList()))
0309                     {
0310                         validResult.appendValidDice(die, die->getValue());
0311                     }
0312                 }
0313                 else
0314                 {
0315                     validResult.appendValidDice(new Die(die), die.getValue());
0316                 }
0317             }
0318         }
0319         break;
0320         case Dice::OnEach:
0321         {
0322             DiceResult* diceResult= getDiceResult(result);
0323             if(nullptr == diceResult)
0324                 break;
0325             for(auto const& die : qAsConst(diceResult->getResultList()))
0326             {
0327                 auto score= validator->hasValid(die, recursive, unlight);
0328                 if(score)
0329                 {
0330                     validResult.appendValidDice(die, score);
0331                 }
0332             }
0333         }
0334         break;
0335         case Dice::OnEachValue:
0336         {
0337             DiceResult* diceResult= getDiceResult(result);
0338             if(nullptr == diceResult)
0339                 break;
0340             for(auto const& die : qAsConst(diceResult->getResultList()))
0341             {
0342                 auto score= validator->hasValid(die, recursive, unlight);
0343                 if(score)
0344                 {
0345                     validResult.appendValidDice(die, score);
0346                 }
0347             }
0348         }
0349         break;
0350         case Dice::AllOfThem:
0351         {
0352             DiceResult* diceResult= getDiceResult(result);
0353             if(nullptr == diceResult)
0354                 break;
0355             auto diceList= diceResult->getResultList();
0356             auto all= std::all_of(diceList.begin(), diceList.end(),
0357                                   [validator, recursive, unlight](Die* die)
0358                                   { return validator->hasValid(die, recursive, unlight); });
0359             if(all)
0360             {
0361                 validResult.setAllTrue(true);
0362                 for(auto die : qAsConst(diceResult->getResultList()))
0363                 {
0364                     validResult.appendValidDice(die, die->getValue());
0365                 }
0366             }
0367         }
0368         break;
0369         case Dice::OneOfThem:
0370         {
0371             DiceResult* diceResult= getDiceResult(result);
0372             if(nullptr == diceResult)
0373                 break;
0374             auto diceList= diceResult->getResultList();
0375             auto any= std::any_of(diceList.begin(), diceList.end(),
0376                                   [validator, recursive, unlight](Die* die)
0377                                   { return validator->hasValid(die, recursive, unlight); });
0378             if(any)
0379             {
0380                 validResult.setAllTrue(true);
0381                 for(auto die : qAsConst(diceResult->getResultList()))
0382                 {
0383                     validResult.appendValidDice(die, die->getValue());
0384                 }
0385             }
0386         }
0387         }
0388         validityData.push_back(validResult);
0389     }
0390     if(validityData.empty())
0391         return;
0392 
0393     int i= 0;
0394     ValidatorResult finalResult;
0395 
0396     for(const auto& vec : validityData)
0397     {
0398         auto diceList= vec.validDice();
0399         if(i == 0)
0400         {
0401             std::copy(diceList.begin(), diceList.end(), std::back_inserter(finalResult.validDiceRef()));
0402         }
0403         else
0404         {
0405             auto id= i - 1;
0406             if(m_operators.size() <= id)
0407                 continue;
0408 
0409             auto op= m_operators.at(id);
0410             switch(op)
0411             {
0412             case Dice::LogicOperation::OR:
0413                 std::copy(diceList.begin(), diceList.end(), std::back_inserter(finalResult.validDiceRef()));
0414                 break;
0415             case Dice::LogicOperation::AND:
0416                 mergeResultsAsAND(vec, finalResult);
0417                 break;
0418             case Dice::LogicOperation::EXCLUSIVE_OR:
0419                 mergeResultsAsExeclusiveOR(vec, finalResult);
0420                 break;
0421             case Dice::LogicOperation::NONE:
0422                 break;
0423             }
0424         }
0425 
0426         ++i;
0427     }
0428 
0429     if(finalResult.allTrue())
0430     {
0431         DiceResult* diceResult= getDiceResult(result);
0432         if(nullptr == diceResult)
0433             return;
0434         auto diceList= diceResult->getResultList();
0435         std::transform(diceList.begin(), diceList.end(), std::back_inserter(finalResult.validDiceRef()),
0436                        [](Die* die) {
0437                            return std::pair<Die*, qint64>({die, 0});
0438                        });
0439     }
0440 
0441     for(auto die : finalResult.validDice())
0442     {
0443         functor(die.first, die.second);
0444     }
0445 }
0446 
0447 ValidatorList* ValidatorList::getCopy() const
0448 {
0449     ValidatorList* val= new ValidatorList();
0450     val->setOperationList(m_operators);
0451     val->setValidators(m_validatorList);
0452     return val;
0453 }