File indexing completed on 2024-04-28 05:36:59

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 "compositevalidator.h"
0023 
0024 #include <map>
0025 
0026 CompositeValidator::CompositeValidator() {}
0027 
0028 CompositeValidator::~CompositeValidator()
0029 {
0030     qDeleteAll(m_validatorList);
0031 }
0032 qint64 CompositeValidator::hasValid(Die* b, bool recursive, bool unhighlight) const
0033 {
0034     int i= 0;
0035     qint64 sum= 0;
0036     bool highLight= false;
0037     for(auto& validator : m_validatorList)
0038     {
0039         qint64 val= validator->hasValid(b, recursive, unhighlight);
0040         if(i == 0)
0041         {
0042             sum= val;
0043             if(b->isHighlighted())
0044             {
0045                 highLight= b->isHighlighted();
0046             }
0047         }
0048         else
0049         {
0050             switch(m_operators.at(i - 1))
0051             {
0052             case OR:
0053                 sum|= val;
0054 
0055                 if(highLight)
0056                 {
0057                     b->setHighlighted(highLight);
0058                 }
0059                 break;
0060             case EXCLUSIVE_OR:
0061                 sum^= val; /// @todo may required to be done by hand
0062                 break;
0063             case AND:
0064                 sum&= val;
0065                 break;
0066             default:
0067                 break;
0068             }
0069         }
0070         ++i;
0071     }
0072 
0073     return sum;
0074 }
0075 
0076 QString CompositeValidator::toString()
0077 {
0078     // m_validatorList
0079     QStringList validatorsTextList;
0080     std::transform(m_validatorList.begin(), m_validatorList.end(), std::back_inserter(validatorsTextList),
0081                    [](Validator* validator) { return validator->toString(); });
0082     QStringList operatorTextList;
0083     std::transform(
0084         m_operators.begin(), m_operators.end(), std::back_inserter(operatorTextList), [](LogicOperation validator) {
0085             static std::map<LogicOperation, QString> map({{OR, "|"}, {EXCLUSIVE_OR, "^"}, {AND, "&"}, {NONE, ""}});
0086             return map[validator];
0087         });
0088 
0089     if(validatorsTextList.size() - 1 != operatorTextList.size())
0090         return QString("Error - operator and validator count don't fit");
0091 
0092     QStringList result;
0093     int i= 0;
0094     for(auto text : validatorsTextList)
0095     {
0096         result << text << operatorTextList[i];
0097 
0098         ++i;
0099     }
0100     return result.join(" ");
0101 }
0102 
0103 Dice::CONDITION_STATE testAND(Dice::CONDITION_STATE before, Dice::CONDITION_STATE current)
0104 {
0105     if(before == Dice::CONDITION_STATE::UNREACHABLE || current == Dice::CONDITION_STATE::UNREACHABLE)
0106         return Dice::CONDITION_STATE::UNREACHABLE;
0107     else if(before == Dice::CONDITION_STATE::ALWAYSTRUE && current == Dice::CONDITION_STATE::ALWAYSTRUE)
0108         return Dice::CONDITION_STATE::ALWAYSTRUE;
0109     else
0110         return Dice::CONDITION_STATE::REACHABLE;
0111 }
0112 
0113 Dice::CONDITION_STATE testOR(Dice::CONDITION_STATE before, Dice::CONDITION_STATE current)
0114 {
0115     if(before == Dice::CONDITION_STATE::UNREACHABLE && current == Dice::CONDITION_STATE::UNREACHABLE)
0116         return Dice::CONDITION_STATE::UNREACHABLE;
0117     else if(before == Dice::CONDITION_STATE::ALWAYSTRUE || current == Dice::CONDITION_STATE::ALWAYSTRUE)
0118         return Dice::CONDITION_STATE::ALWAYSTRUE;
0119     else
0120         return Dice::CONDITION_STATE::REACHABLE;
0121 }
0122 
0123 Dice::CONDITION_STATE testXOR(Dice::CONDITION_STATE before, Dice::CONDITION_STATE current)
0124 {
0125     if(before == current
0126        && (before == Dice::CONDITION_STATE::UNREACHABLE || before == Dice::CONDITION_STATE::ALWAYSTRUE))
0127         return Dice::CONDITION_STATE::UNREACHABLE;
0128     else if((before != current)
0129             && (before == Dice::CONDITION_STATE::ALWAYSTRUE || before == Dice::CONDITION_STATE::UNREACHABLE)
0130             && (before != Dice::CONDITION_STATE::REACHABLE || current != Dice::CONDITION_STATE::REACHABLE))
0131         return Dice::CONDITION_STATE::ALWAYSTRUE;
0132     else
0133         return Dice::CONDITION_STATE::REACHABLE;
0134 }
0135 
0136 Dice::CONDITION_STATE CompositeValidator::isValidRangeSize(const std::pair<qint64, qint64>& range) const
0137 {
0138     std::vector<Dice::CONDITION_STATE> vec;
0139     std::transform(
0140         m_validatorList.begin(), m_validatorList.end(), std::back_inserter(vec),
0141         [range](Validator* validator) -> Dice::CONDITION_STATE { return validator->isValidRangeSize(range); });
0142 
0143     auto itError= std::find(vec.begin(), vec.end(), Dice::CONDITION_STATE::ERROR_STATE);
0144 
0145     if((static_cast<int>(vec.size()) != m_operators.size() + 1) || (itError != vec.end()))
0146     {
0147         return Dice::CONDITION_STATE::ERROR_STATE;
0148     }
0149 
0150     std::size_t i= 0;
0151     Dice::CONDITION_STATE val= Dice::CONDITION_STATE::ERROR_STATE;
0152     for(const auto& op : m_operators)
0153     {
0154         auto currentState= vec[i + 1];
0155         if(i == 0)
0156         {
0157             val= vec[i];
0158         }
0159         switch(op)
0160         {
0161         case OR:
0162             val= testAND(val, currentState);
0163             break;
0164         case EXCLUSIVE_OR:
0165             val= testOR(val, currentState);
0166             break;
0167         case AND:
0168             val= testXOR(val, currentState);
0169             break;
0170         case NONE:
0171             val= Dice::CONDITION_STATE::ERROR_STATE;
0172             break;
0173         }
0174 
0175         ++i;
0176     }
0177     return val;
0178 }
0179 
0180 void CompositeValidator::setOperationList(const QVector<LogicOperation>& m)
0181 {
0182     m_operators= m;
0183 }
0184 
0185 void CompositeValidator::setValidatorList(const QList<Validator*>& valids)
0186 {
0187     qDeleteAll(m_validatorList);
0188     m_validatorList= valids;
0189 }
0190 Validator* CompositeValidator::getCopy() const
0191 {
0192     CompositeValidator* val= new CompositeValidator();
0193     val->setOperationList(m_operators);
0194     val->setValidatorList(m_validatorList);
0195     return val;
0196 }