diff options
| -rw-r--r-- | src/bin/cli/main.cpp | 4 | ||||
| -rw-r--r-- | src/libparser/booleancondition.h | 1 | ||||
| -rw-r--r-- | src/libparser/die.cpp | 4 | ||||
| -rw-r--r-- | src/libparser/die.h | 2 | ||||
| -rw-r--r-- | src/libparser/node/explodedicenode.cpp | 43 | ||||
| -rw-r--r-- | src/libparser/node/rerolldicenode.cpp | 37 | ||||
| -rw-r--r-- | src/libparser/validatorlist.cpp | 7 | ||||
| -rw-r--r-- | src/libparser/validatorlist.h | 2 | ||||
| -rw-r--r-- | src/tests/dice/tst_dice.cpp | 72 |
9 files changed, 162 insertions, 10 deletions
diff --git a/src/bin/cli/main.cpp b/src/bin/cli/main.cpp index 2864c27..91fa1ef 100644 --- a/src/bin/cli/main.cpp +++ b/src/bin/cli/main.cpp @@ -597,10 +597,6 @@ int main(int argc, char* argv[]) for(auto& cmd : cmdList) cmd= QUrl::fromPercentEncoding(cmd.toUtf8()); - qDebug() << "cmdList" << cmdList; - // cmdList << "(1)-1d4e4mk00;300;[$1\u0004$3]k1;0100;200;300;[$1,$2,$3]k1TK\u0004;$1+$1;$2i:[<1]{1}{0}"; - cmdList << "1d4e4mk00;300;100;[$1,$2,$3]k1TK\u0004"; - QJsonArray aliases; if(optionParser.isSet(alias)) { diff --git a/src/libparser/booleancondition.h b/src/libparser/booleancondition.h index d49c5fe..88f5c07 100644 --- a/src/libparser/booleancondition.h +++ b/src/libparser/booleancondition.h @@ -49,7 +49,6 @@ public: */ virtual Validator* getCopy() const override; -private: qint64 valueToScalar() const; private: diff --git a/src/libparser/die.cpp b/src/libparser/die.cpp index 021ba5e..c1888b3 100644 --- a/src/libparser/die.cpp +++ b/src/libparser/die.cpp @@ -165,6 +165,8 @@ void Die::replaceLastValue(qint64 value) void Die::roll(bool adding) { + if(m_base > m_maxValue) + return; std::uniform_int_distribution<qint64> dist(m_base, m_maxValue); qint64 value= dist(s_rng); if((adding) || (m_rollResult.isEmpty())) @@ -213,7 +215,7 @@ void Die::setBase(qint64 base) { m_base= base; } -qint64 Die::getBase() +qint64 Die::getBase() const { return m_base; } diff --git a/src/libparser/die.h b/src/libparser/die.h index 48da214..0fe36fd 100644 --- a/src/libparser/die.h +++ b/src/libparser/die.h @@ -123,7 +123,7 @@ public: * @brief setBase */ void setBase(qint64); - qint64 getBase(); + qint64 getBase() const; QString getColor() const; void setColor(const QString& color); diff --git a/src/libparser/node/explodedicenode.cpp b/src/libparser/node/explodedicenode.cpp index 136611a..f4c699d 100644 --- a/src/libparser/node/explodedicenode.cpp +++ b/src/libparser/node/explodedicenode.cpp @@ -1,5 +1,7 @@ #include "explodedicenode.h" +#include "booleancondition.h" #include "diceparser/parsingtoolbox.h" +#include "validator.h" #include "validatorlist.h" ExplodeDiceNode::ExplodeDiceNode() : m_diceResult(new DiceResult()) @@ -21,11 +23,43 @@ void ExplodeDiceNode::run(ExecutionNode* previous) if(!previous_result) return; - for(auto& die : previous_result->getResultList()) + auto diceList= previous_result->getResultList(); + + auto allInvalid= std::all_of(std::begin(diceList), std::end(diceList), + [](const Die* die) { return die->getMaxValue() < die->getBase(); }); + + qint64 maxVal= 0; + if(allInvalid) + { + + auto const& list= m_validatorList->validators(); + auto max= std::max_element(std::begin(list), std::end(list), + [](Validator* a, Validator* b) + { + auto aa= dynamic_cast<BooleanCondition*>(a); + auto bb= dynamic_cast<BooleanCondition*>(b); + + if(bb && aa) + return aa->valueToScalar() < bb->valueToScalar(); + else + return (!bb && aa); + }); + + auto maxCondition= dynamic_cast<BooleanCondition*>(*max); + if(maxCondition) + maxVal= maxCondition->valueToScalar(); + } + + for(auto& die : diceList) { Die* tmpdie= new Die(*die); m_diceResult->insertResult(tmpdie); die->displayed(); + if(allInvalid && maxVal != tmpdie->getMaxValue() && maxVal > tmpdie->getBase()) + { + qInfo() << "Invalid range for explosing dice, set " << maxVal << " as maximum" << tmpdie->getMaxValue(); + tmpdie->setMaxValue(maxVal); + } } qint64 limit= -1; @@ -51,6 +85,13 @@ void ExplodeDiceNode::run(ExecutionNode* previous) .arg(static_cast<int>(die->getBase())) .arg(static_cast<int>(die->getMaxValue())))); + isValid(die->getBase() > die->getMaxValue(), Dice::ERROR_CODE::ENDLESS_LOOP_ERROR, + QObject::tr("Condition (%1) cause an endless loop with dice: %2") + .arg(toString(true)) + .arg(QStringLiteral("d[%1,%2]") + .arg(static_cast<int>(die->getBase())) + .arg(static_cast<int>(die->getMaxValue())))); + hasExploded= true; if(limit >= 0) { diff --git a/src/libparser/node/rerolldicenode.cpp b/src/libparser/node/rerolldicenode.cpp index 25143ac..7e5bda3 100644 --- a/src/libparser/node/rerolldicenode.cpp +++ b/src/libparser/node/rerolldicenode.cpp @@ -1,5 +1,6 @@ #include <diceparser/parsingtoolbox.h> +#include "booleancondition.h" #include "rerolldicenode.h" #include "validatorlist.h" #include <utility> @@ -37,7 +38,34 @@ void RerollDiceNode::run(ExecutionNode* previous) m_result->setPrevious(previous_result); - for(auto const& die : previous_result->getResultList()) + QList<Die*>& list1= previous_result->getResultList(); + + auto allInvalid= std::all_of(std::begin(list1), std::end(list1), + [](const Die* die) { return die->getMaxValue() < die->getBase(); }); + + qint64 maxVal= 0; + if(allInvalid) + { + + auto const& list1= m_validatorList->validators(); + auto max= std::max_element(std::begin(list1), std::end(list1), + [](Validator* a, Validator* b) + { + auto aa= dynamic_cast<BooleanCondition*>(a); + auto bb= dynamic_cast<BooleanCondition*>(b); + + if(bb && aa) + return aa->valueToScalar() < bb->valueToScalar(); + else + return (!bb && aa); + }); + + auto maxCondition= dynamic_cast<BooleanCondition*>(*max); + if(maxCondition) + maxVal= maxCondition->valueToScalar(); + } + + for(auto const& die : list1) { if(!die) return; @@ -45,6 +73,13 @@ void RerollDiceNode::run(ExecutionNode* previous) Die* tmpdie= new Die(*die); m_diceResult->insertResult(tmpdie); die->displayed(); + + if(allInvalid && maxVal != tmpdie->getMaxValue() && maxVal > tmpdie->getBase()) + { + qInfo() << "Invalid range for explosing dice, set " << maxVal << " as maximum" << tmpdie->getMaxValue() + << tmpdie->getBase(); + tmpdie->setMaxValue(maxVal); + } } QList<Die*>& list= m_diceResult->getResultList(); diff --git a/src/libparser/validatorlist.cpp b/src/libparser/validatorlist.cpp index 17568d1..41bc24f 100644 --- a/src/libparser/validatorlist.cpp +++ b/src/libparser/validatorlist.cpp @@ -25,8 +25,8 @@ #include "result/result.h" #include "validator.h" #include <QDebug> -#include <utility> #include <QLoggingCategory> +#include <utility> Q_LOGGING_CATEGORY(DiceCat, "DiceParser") @@ -456,3 +456,8 @@ ValidatorList* ValidatorList::getCopy() const val->setValidators(m_validatorList); return val; } + +const QList<Validator*>& ValidatorList::validators() const +{ + return m_validatorList; +} diff --git a/src/libparser/validatorlist.h b/src/libparser/validatorlist.h index ad2c9d4..9248426 100644 --- a/src/libparser/validatorlist.h +++ b/src/libparser/validatorlist.h @@ -91,6 +91,8 @@ public: void validResult(Result* result, bool recursive, bool unlight, std::function<void(Die*, qint64)> functor) const; + const QList<Validator*>& validators() const; + private: QVector<Dice::LogicOperation> m_operators; QList<Validator*> m_validatorList; diff --git a/src/tests/dice/tst_dice.cpp b/src/tests/dice/tst_dice.cpp index 2de3bcc..d6b9de3 100644 --- a/src/tests/dice/tst_dice.cpp +++ b/src/tests/dice/tst_dice.cpp @@ -24,6 +24,7 @@ #include "diceparser/dicealias.h" #include "diceparser/diceparser.h" +#include "diceparser/diceparserhelper.h" #include "die.h" // node @@ -206,6 +207,9 @@ private slots: void deterministTest(); void deterministTest_data(); + void listValueWithOption(); + void listValueWithOption_data(); + private: std::unique_ptr<Die> m_die; std::unique_ptr<DiceParser> m_diceParser; @@ -1382,6 +1386,74 @@ void TestDice::deterministTest_data() // 1d6;10d10e10k\$1 } +void TestDice::listValueWithOption() +{ + QFETCH(QString, command); + QFETCH(int, results); + QFETCH(Dice::CompareOperator, theOperator); + QFETCH(bool, error); + + auto parsing= m_diceParser->parseLine(command); + if(!error) + QVERIFY2(parsing, "parsing"); + + if(parsing) + m_diceParser->start(); + + if(error) + { + QVERIFY2(!m_diceParser->humanReadableError().isEmpty() || !m_diceParser->humanReadableWarning().isEmpty(), + "no error"); + return; + } + else + { + QVERIFY2(m_diceParser->humanReadableError().isEmpty(), "no error"); + QVERIFY2(m_diceParser->humanReadableWarning().isEmpty(), "no warning"); + } + + auto resultCmd= m_diceParser->scalarResultsFromEachInstruction(); + + auto resultCommand= resultCmd.at(0); + + switch(theOperator) + { + case Dice::CompareOperator::GreaterThan: + QVERIFY(results < resultCommand); + break; + case Dice::CompareOperator::LesserThan: + QVERIFY(results > resultCommand); + break; + case Dice::CompareOperator::LesserOrEqual: + qDebug() << results << " " << resultCommand; + QVERIFY(results >= resultCommand); + break; + default: + break; + } +} + +void TestDice::listValueWithOption_data() +{ + QTest::addColumn<QString>("command"); + QTest::addColumn<int>("results"); + QTest::addColumn<Dice::CompareOperator>("theOperator"); + QTest::addColumn<bool>("error"); + + // explode + QTest::addRow("cmd1") << "[10]e10" << 10 << Dice::CompareOperator::GreaterThan << false; + QTest::addRow("cmd2") << "[10]e10" << std::numeric_limits<int>::max() << Dice::CompareOperator::LesserThan << false; + // add + QTest::addRow("cmd3") << "[10]a10" << 10 << Dice::CompareOperator::GreaterThan << false; + QTest::addRow("cmd4") << "[10]a10" << 20 << Dice::CompareOperator::LesserOrEqual << false; + // reroll + QTest::addRow("cmd3") << "[10]r10" << 0 << Dice::CompareOperator::GreaterThan << false; + QTest::addRow("cmd4") << "[10]r10" << 11 << Dice::CompareOperator::LesserOrEqual << false; + // reroll until + QTest::addRow("cmd5") << "[10]R10" << 10 << Dice::CompareOperator::LesserOrEqual << false; + QTest::addRow("cmd6") << "[10]R1" << 10 << Dice::CompareOperator::LesserOrEqual << false; +} + void TestDice::cleanupTestCase() {} QTEST_MAIN(TestDice) |