File indexing completed on 2024-05-12 17:11:34
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 }