aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.travis.yml32
-rw-r--r--CMakeLists.txt63
-rw-r--r--HelpMe.md92
-rw-r--r--cli/CMakeLists.txt57
-rw-r--r--cli/main.cpp1
-rw-r--r--diceparser.cpp12
-rw-r--r--diceparser.h10
-rw-r--r--diceparser.pri2
-rw-r--r--diceroller.cpp11
-rw-r--r--node/valueslistnode.cpp6
-rw-r--r--tests/CMakeLists.txt9
-rw-r--r--tests/dice/CMakeLists.txt17
-rw-r--r--tests/dice/Dice.pro25
-rw-r--r--tests/testnode.cpp (renamed from node/testnode.cpp)1
-rw-r--r--tests/testnode.h (renamed from node/testnode.h)0
-rw-r--r--tests/tst_dice.cpp940
16 files changed, 1169 insertions, 109 deletions
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..861ec30
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,32 @@
+language: cpp
+
+matrix:
+ include:
+ - dist: xenial
+ compiler: clang
+ before_install:
+ - sudo add-apt-repository -y ppa:beineri/opt-qt-5.12.3-xenial
+ - sudo apt-get -qy update
+ install:
+ - sudo apt-get -qy install qt512svg qt512base qt512translations qt512tools mesa-common-dev libglu1-mesa-dev freeglut3-dev
+
+ - os: osx
+ osx_image: xcode10
+ before_install:
+ - travis_wait 30 brew update
+ before_script:
+ - sudo Xvfb :99 -ac -screen 0 1024x768x8 &
+ install:
+ - brew install cppcheck
+ - brew install qt5
+ - brew link --force qt && sudo ln -s /usr/local/Cellar/qt/5.13.0/mkspecs /usr/local/mkspecs && sudo ln -s /usr/local/Cellar/qt/5.13.0/plugins /usr/local/plugins
+ #env:
+ #- CMAKE_PREFIX_PATH=/usr/local/Cellar/qt/5.13.0
+ #- PATH=/usr/local/opt/qt5/bin:$PATH
+
+script:
+ - mkdir -p build
+ - pushd build
+ - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then (cmake ../ && make -j4 && xvfb-run env CTEST_OUTPUT_ON_FAILURE=1 make test) fi
+ - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then (cmake ../ && make -j4 && env CTEST_OUTPUT_ON_FAILURE=1 make test) fi
+ - popd
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9460032..9a9a340 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,12 +1,63 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 3.5)
project(diceparser)
-#add_subdirectory(irc)
-add_subdirectory(cli)
-#add_subdirectory(mobile)
-#add_subdirectory(webserver)
+set(QT_REQUIRED_VERSION "5.12.0")
+find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Core Test Gui Svg)
+
+enable_testing(true)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR} result node)
+SET( dice_sources
+ diceparser.cpp
+ range.cpp
+ booleancondition.cpp
+ validator.cpp
+ compositevalidator.cpp
+ operationcondition.cpp
+ die.cpp
+ parsingtoolbox.cpp
+ dicealias.cpp
+ result/result.cpp
+ result/scalarresult.cpp
+ result/stringresult.cpp
+ result/diceresult.cpp
+ node/countexecutenode.cpp
+ node/dicerollernode.cpp
+ node/executionnode.cpp
+ node/explodedicenode.cpp
+ node/helpnode.cpp
+ node/mergenode.cpp
+ node/jumpbackwardnode.cpp
+ node/keepdiceexecnode.cpp
+ node/listaliasnode.cpp
+ node/listsetrollnode.cpp
+ node/numbernode.cpp
+ node/parenthesesnode.cpp
+ # node/forloopnode.cpp
+ node/paintnode.cpp
+ node/rerolldicenode.cpp
+ node/scalaroperatornode.cpp
+ node/sortresult.cpp
+ node/startingnode.cpp
+ node/filternode.cpp
+ node/stringnode.cpp
+ node/ifnode.cpp
+ node/splitnode.cpp
+ node/groupnode.cpp
+ node/bind.cpp
+ node/occurencecountnode.cpp
+ node/uniquenode.cpp
+ highlightdice.cpp
+ node/variablenode.cpp
+ node/valueslistnode.cpp
+)
-#qt5_use_modules()
+add_library(diceparser SHARED ${dice_sources} )
+target_link_libraries(diceparser PUBLIC Qt5::Core Qt5::Gui Qt5::Svg)
+add_subdirectory(cli)
+add_subdirectory( tests )
+#add_subdirectory(irc)
+#add_subdirectory(mobile)
+#add_subdirectory(webserver)
diff --git a/HelpMe.md b/HelpMe.md
index 94f6dce..f6a11c1 100644
--- a/HelpMe.md
+++ b/HelpMe.md
@@ -2,9 +2,9 @@
# Table of Contents
-* [DiceParser](#diceparser--what-is-it-)
-* [Roll a die](#how-to-roll-a-die)
-* [List of operator](#list-of-operator)
+* [DiceParser](#diceparser--what-is-it-)
+* [Roll a die](#how-to-roll-a-die)
+* [List of operator](#list-of-operator)
* [Keep](#keep)
* [Explode and Keep](#explode-and-keep)
* [Keep Lower dice](#keep-lower-dice)
@@ -22,12 +22,13 @@
* [Group](#group)
* [Spread](#spread)
* [Unique](#unique)
+ * [Value list](#Value-list)
* [Comment (\#)](#comment-)
-* [Arithmetic](#arithmetic)
-* [Arithmetic and Dice](#arithmetic-and-dice)
-* [Validator](#validator)
-* [Value from set](#select-value-from-list)
-* [Miscellaneous examples](#examples)
+* [Arithmetic](#arithmetic)
+* [Arithmetic and Dice](#arithmetic-and-dice)
+* [Validator](#validator)
+* [Value from set](#select-value-from-list)
+* [Miscellaneous examples](#examples)
* [Best Practices](#best-practices)
* [Platforms](#roll-dice-on-each-platform)
* [Discord bot](#discord-bot)
@@ -42,12 +43,12 @@ Such as: Irc bot, discord bot, included in Rolisteam, web server, on twitter etc
## About examples in this documentation
-To make it clear, all examples in this documentation do not show the start up prefix.
-Please, remember to add the proper prefix given where you run dice command: Rolisteam, discord, IRC…
-If you don't know, try `!`.
+To make it clear, all examples in this documentation do not show the start up prefix.
+Please, remember to add the proper prefix given where you run dice command: Rolisteam, discord, IRC…
+If you don't know, try `!`.
The prefix allows the system to identify your command.
-## How to roll a die
+## How to roll a die
It is real simple. you have to call:
> 1d6
@@ -89,7 +90,7 @@ Rolling 3 dice with 10 faces starting at 0.
Rolling 3 dice, values are between -20 and -9.
-### Instruction: Roll two (or more) kinds of dice at once
+### Instruction: Roll two (or more) kinds of dice at once
Adding (or any arithmetic operations) results from two (or more) kinds of dice is easy:
@@ -106,8 +107,8 @@ or
### Merge
-It is possible to merge every instruction inside a huge one.
-The operator merge is dedicated to that.
+It is possible to merge every instruction inside a huge one.
+The operator merge is dedicated to that.
It is useful when you need to manage all diceresult as the same result.
For example, if you need to keep the higher dice between a d6 and d8.
@@ -127,7 +128,7 @@ the number of instruction is not limited.
> 8d10;$1c[>6];$1c1;$2-$3
-* The first instruction rolls 8 (10 sided) dice
+* The first instruction rolls 8 (10 sided) dice
* The second instruction counts how many dice are higher than 6.
* The third instruction counts how many dice are equal to 1.
* The fourth instruction substracts the result of the third instruction to the result of seconde one.
@@ -248,10 +249,19 @@ Result: `2x8 - [1,2,3,5,6,7,8,8,9,10]`
Count and sort occurence when they occur at least 2 times, the value should respect the validator (here less than 6).
Result: `2x3,2x5 - [3,3,5,5,6,6,6,7,7,8]`
+
+#### Errors
+
+> 10d10o[<6]
+
+This command is triggering a warning. As occurence operator can have 0 or 2 parameters. But only one validator is unsupported yet.
+
+
+
### Backward Jump
This operator is dedicated to apply its next operator to the second to last result.
-For example:
+For example:
> 8D10c[>=7]+@c[=10]
@@ -263,7 +273,7 @@ c[=10] in this command is counting the number of 10 in the result of 8D10, if yo
Paint the first die in the list in blue
-> 8d10p[2:blue]
+> 8d10p[2:blue]
Paint the two first dice in the list in blue.
@@ -300,19 +310,29 @@ It makes exploded dice as new dice.
> 4d6e6u
-
Result: 6 4 3 3 2
Final result: 6+4+3 = 13
+### Value list
+
+Build your own value list and apply any dice operator.
+
+> [10,25,43,8]k1
+
+Get the higher score from several instruction:
+
+> 1d10;2d6+9;1d20;[$1,$2,$3,$4]k1
+
+Each value is transformed into a die.
### Bind
-Bind works exactly as merge but one thing.
+Bind works exactly as merge but it keeps instruction array untouched.
> !2d8;2d12b;$2k2;$2k2kl1;"your total is $3 with lowest: $4"
Roll two 8-sided dice and two 12-sided dice then bind their results. using this final result, we keep the 2 higher dice and then we isolate the lowest of the two highest.
-At the end, we display the result inside a setence.
+At the end, we display the result inside a sentence.
### if
@@ -415,8 +435,8 @@ or
In this example, the critical fail happens when there are more fails than success.
-
-
+
+
In the next example, the critical fail happens when there was no success and a least one fail.
> 8d10;$1c[>6];$1c1;$2-$3;$4i:[=0]{"Fail $4 [%2]"}{$4i:[>0]{"$2 Success[%2]"}{$2i:[=0]{"Critical Fail $4 [%2]"}{"Fail $4 [%2]"}}}
@@ -428,7 +448,7 @@ Group dices, then count the number of group (7th sea system).
#### Example
-> 3d20g10
+> 3d20g10
This will roll 3 dices and then try to group them to make groups of 10. If you get `9 9 2`, you can only create one group whose value is more or equal to ten (`{9,2}`, the second `9` being "wasted").
@@ -437,7 +457,7 @@ The `g` operator is allowed to re-order dices to create groups. When rolling `4d
### Comment (\#)
-> 2D6 # Sword attack
+> 2D6 # Sword attack
Display "Sword attack" and the result of the two dice.
DiceParser ignore everything after the \#. The whole part is treated as one comment.
@@ -452,7 +472,7 @@ yes
## Arithmetic
-Rolisteam Dice Parser is able to compute primary arithmetic operation such as: +, -, /, * and it also manages those operator priority and it can also manage parenthesis.
+Rolisteam Dice Parser is able to compute primary arithmetic operation such as: +, -, /, * and it also manages those operator priority and it can also manage parenthesis.
> 8+8+8
@@ -484,8 +504,8 @@ Result: 2.5
## Arithmetic and Dice
-It is possible to use arithmetic opearation on dice. Please pay attention that the default operation to translate a
-dice list to scalar is the sum. So if you roll `3d6`, the result will be a list with 3 values {2, 5 ,1}. Now, we
+It is possible to use arithmetic opearation on dice. Please pay attention that the default operation to translate a
+dice list to scalar is the sum. So if you roll `3d6`, the result will be a list with 3 values {2, 5 ,1}. Now, we
change a bit the command `3d6+4`: It is resolved like this: {2, 5 ,1} = 8; 8+4 = 12. The final result is 12.
> 3d6+4
@@ -502,14 +522,14 @@ Substract the result of 1 die to 87
> (6-4)D10
-Substract 4 to 6 and then roll two dice.
+Substract 4 to 6 and then roll two dice.
> 1D10/2
Divide by 2 the result of 1 die.
> (2+2)^2
-Result: 16
+Result: 16
> 1d10^2
@@ -529,7 +549,7 @@ There are three kind of Validator:
Any operator which requires validator (such as `a,r,e,c`) can use those three kind.
-### Scalar
+### Scalar
The scalar value sets the validator on eguality between the dice value and the validator
@@ -612,7 +632,7 @@ compute: 24
> 1L[sword,bow,knife,gun,shotgun]
-One of this word will be picked.
+One of this word will be picked.
> 8D10c[Validator1]-@c[validator2]
@@ -624,7 +644,7 @@ Old World in darkness system.
> 8D10c[>=7]+@c[=10]
-Exalted 2nd edition system.
+Exalted 2nd edition system.
## Best Practices
@@ -682,7 +702,7 @@ The k operator to keeps as many dice as you roll is pretty useless because it is
### To change the prefix
> !prefix set newprefix
-/!\ Please, don't set "newprefix" as your new prefix.
+/!\ Please, don't set "newprefix" as your new prefix.
### Set the prefix by default
@@ -694,7 +714,7 @@ The k operator to keeps as many dice as you roll is pretty useless because it is
> roll 2d6
-> rollprefix set !
+> rollprefix set !
# Macro management
@@ -761,5 +781,3 @@ All lines must be part of the same messages, so prepare it first.
Please fulfill a ticket in our [Bug tracker](https://github.com/Rolisteam/DiceParser/issues) system.
Or contact us on [discord](https://discordapp.com/invite/MrMrQwX) or any [other ways](http://www.rolisteam.org/contact.html)
-
-
diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt
index 5886240..215287d 100644
--- a/cli/CMakeLists.txt
+++ b/cli/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 3.5)
option(UPDATE_TRANSLATIONS "update Translation" OFF)
MESSAGE(STATUS "UPDATE TRANSLATIONS: ${UPDATE_TRANSLATIONS}")
@@ -14,7 +14,6 @@ set(CMAKE_AUTOMOC ON)
set(EXECUTABLE_OUTPUT_PATH bin/)
-
# Find the QtWidgets library
find_package(Qt5Core)
include_directories(${Qt5Core_INCLUDES} ../)
@@ -36,9 +35,9 @@ ADD_DEFINITIONS(
)
set(dice_RESOURCES diceparser.qrc)
-FIND_PACKAGE(Qt5LinguistTools)
+find_package(Qt5LinguistTools)
find_package(Qt5Svg)
-
+
IF(UPDATE_TRANSLATIONS)
MESSAGE( update Translation )
@@ -67,58 +66,14 @@ if(Qt5Core_FOUND)
get_filename_component(QT_LIBRARY_DIR ${QT_LIBRARY_DIR} PATH)
endif()
-SET( dice_sources
- ../diceparser.cpp
- ../range.cpp
- ../booleancondition.cpp
- ../validator.cpp
- ../compositevalidator.cpp
- ../operationcondition.cpp
- ../die.cpp
- ../parsingtoolbox.cpp
- ../dicealias.cpp
- ../result/result.cpp
- ../result/scalarresult.cpp
- ../result/stringresult.cpp
- ../result/diceresult.cpp
- ../node/countexecutenode.cpp
- ../node/dicerollernode.cpp
- ../node/executionnode.cpp
- ../node/explodedicenode.cpp
- ../node/helpnode.cpp
- ../node/mergenode.cpp
- ../node/jumpbackwardnode.cpp
- ../node/keepdiceexecnode.cpp
- ../node/listaliasnode.cpp
- ../node/listsetrollnode.cpp
- ../node/numbernode.cpp
- ../node/parenthesesnode.cpp
- ../node/valueslistnode.cpp
-# ../node/forloopnode.cpp
- ../node/paintnode.cpp
- ../node/rerolldicenode.cpp
- ../node/scalaroperatornode.cpp
- ../node/sortresult.cpp
- ../node/startingnode.cpp
- ../node/filternode.cpp
- ../node/stringnode.cpp
- ../node/ifnode.cpp
- ../node/splitnode.cpp
- ../node/groupnode.cpp
- ../node/bind.cpp
- ../node/occurencecountnode.cpp
- ../node/uniquenode.cpp
+SET( cli_sources
main.cpp
displaytoolbox.cpp
- ../highlightdice.cpp
- ../node/variablenode.cpp
)
set(documentation_files ../HelpMe.md ../README.md)
-add_executable( dice ${dice_sources} ${dice_QM} ${documentation_files})
+add_executable( dice ${cli_sources} ${dice_QM} ${documentation_files})
-target_link_libraries(dice ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Svg_LIBRARIES})
+target_link_libraries(dice diceparser ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Svg_LIBRARIES})
INSTALL_TARGETS(/bin dice)
-
-#qt5_use_modules()
diff --git a/cli/main.cpp b/cli/main.cpp
index f2de0f2..d6f6398 100644
--- a/cli/main.cpp
+++ b/cli/main.cpp
@@ -38,6 +38,7 @@
#include "diceparser.h"
#include "displaytoolbox.h"
#include "highlightdice.h"
+#include "parsingtoolbox.h"
/**
* @page Dice
diff --git a/diceparser.cpp b/diceparser.cpp
index e01373c..75247ba 100644
--- a/diceparser.cpp
+++ b/diceparser.cpp
@@ -28,6 +28,7 @@
#include "node/bind.h"
#include "node/countexecutenode.h"
+#include "node/dicerollernode.h"
#include "node/explodedicenode.h"
#include "node/filternode.h"
#include "node/groupnode.h"
@@ -52,6 +53,11 @@
#include "node/valueslistnode.h"
#include "node/variablenode.h"
+#include "booleancondition.h"
+#include "parsingtoolbox.h"
+#include "range.h"
+#include "validator.h"
+
#define DEFAULT_FACES_NUMBER 10
DiceParser::DiceParser()
@@ -337,6 +343,12 @@ bool DiceParser::readValuesList(QString& str, ExecutionNode*& node)
variableNode->setData(&m_startNodes);
values->insertValue(variableNode);
}
+ else if(ParsingToolBox::readNumber(var, number))
+ {
+ NumberNode* numberNode= new NumberNode();
+ numberNode->setNumber(number);
+ values->insertValue(numberNode);
+ }
}
node= values;
return true;
diff --git a/diceparser.h b/diceparser.h
index a5e8619..8ecfb50 100644
--- a/diceparser.h
+++ b/diceparser.h
@@ -25,20 +25,16 @@
#include <QMap>
#include <QString>
-#include "node/dicerollernode.h"
-#include "node/executionnode.h"
-
-#include "booleancondition.h"
#include "dicealias.h"
#include "highlightdice.h"
-#include "parsingtoolbox.h"
-#include "range.h"
-#include "validator.h"
+#include "node/executionnode.h"
typedef QList<HighLightDice> ListDiceResult;
typedef QMap<quint64, ListDiceResult> ExportedDiceResult;
class ExplodeDiceNode;
+class ParsingToolBox;
+class DiceRollerNode;
/**
* @page DiceParser Dice Parser
*
diff --git a/diceparser.pri b/diceparser.pri
index 8bdd93f..2424c18 100644
--- a/diceparser.pri
+++ b/diceparser.pri
@@ -32,7 +32,6 @@ SOURCES += $$PWD/diceparser.cpp \
$$PWD/node/explodedicenode.cpp \
$$PWD/node/parenthesesnode.cpp \
$$PWD/node/helpnode.cpp \
- $$PWD/node/testnode.cpp \
$$PWD/node/jumpbackwardnode.cpp \
$$PWD/node/mergenode.cpp \
$$PWD/node/listaliasnode.cpp \
@@ -75,7 +74,6 @@ HEADERS += \
$$PWD/node/scalaroperatornode.h \
$$PWD/node/numbernode.h \
$$PWD/node/sortresult.h \
- $$PWD/node/testnode.h \
$$PWD/node/keepdiceexecnode.h \
$$PWD/node/countexecutenode.h \
$$PWD/node/explodedicenode.h \
diff --git a/diceroller.cpp b/diceroller.cpp
index d343fcb..de501e9 100644
--- a/diceroller.cpp
+++ b/diceroller.cpp
@@ -179,9 +179,10 @@ QString DiceRoller::getError() const
void DiceRoller::setError(const QString& error)
{
- if(m_error != error)
- {
- m_error= error;
- emit errorOccurs();
- }
+ if(m_error == error)
+ return;
+
+ m_error= error;
+ emit errorOccurs();
}
+
diff --git a/node/valueslistnode.cpp b/node/valueslistnode.cpp
index e022741..b31ee84 100644
--- a/node/valueslistnode.cpp
+++ b/node/valueslistnode.cpp
@@ -1,5 +1,7 @@
#include "valueslistnode.h"
+#include "variablenode.h"
+
ValuesListNode::ValuesListNode() : m_diceResult(new DiceResult())
{
m_result= m_diceResult;
@@ -16,7 +18,9 @@ void ValuesListNode::run(ExecutionNode* previous)
continue;
auto val= result->getResult(Result::SCALAR).toInt();
Die* die= new Die();
- die->displayed();
+ auto dyna= dynamic_cast<VariableNode*>(node);
+ if(nullptr != dyna)
+ die->displayed();
die->insertRollValue(val);
m_diceResult->insertResult(die);
}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..4065cc5
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,9 @@
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-permissive -pedantic -Wall -Wextra")
+set(CMAKE_AUTOMOC ON)
+find_package(Qt5Test REQUIRED)
+
+set(test_source testnode.cpp tst_dice.cpp)
+
+add_executable(test_dice ${test_source} )
+target_link_libraries(test_dice diceparser Qt5::Test)
+add_test(tst_diceparser test_dice)
diff --git a/tests/dice/CMakeLists.txt b/tests/dice/CMakeLists.txt
new file mode 100644
index 0000000..a0f27fd
--- /dev/null
+++ b/tests/dice/CMakeLists.txt
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 3.5)
+project(tst_diceParser)
+
+enable_testing(true)
+
+# Tell CMake to run moc when necessary:
+set(CMAKE_AUTOMOC ON)
+
+# As moc files are generated in the binary dir, tell CMake
+# to always look for includes there:
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+find_package(Qt5Test REQUIRED)
+
+add_test(tst_diceParser tst_dice.cpp)
+
+target_link_libraries(foo Qt5::Test)
diff --git a/tests/dice/Dice.pro b/tests/dice/Dice.pro
new file mode 100644
index 0000000..9d24f91
--- /dev/null
+++ b/tests/dice/Dice.pro
@@ -0,0 +1,25 @@
+include(../tests.pri)
+
+SOURCES += \
+ tst_dice.cpp
+
+TEMPLATE = app
+TARGET= tst_diceParser
+MOC_DIR=trash
+OBJECTS_DIR=trash
+
+CONFIG+=testcase
+
+QT += testlib quick qml widgets
+
+INCLUDEPATH += $$ROLISTEAMSRC/diceparser/
+INCLUDEPATH += $$ROLISTEAMSRC/diceparser/node
+INCLUDEPATH += $$ROLISTEAMSRC/diceparser/result
+
+
+include($$ROLISTEAMSRC/diceparser/diceparser.pri)
+
+HEADERS -= ../../../rolisteam/client/diceparser/qmltypesregister.h
+SOURCES -= ../../../rolisteam/client/diceparser/qmltypesregister.cpp
+
+
diff --git a/node/testnode.cpp b/tests/testnode.cpp
index 263286b..de9fc05 100644
--- a/node/testnode.cpp
+++ b/tests/testnode.cpp
@@ -10,6 +10,7 @@ TestNode::~TestNode()
}
void TestNode::run(ExecutionNode* previous)
{
+ Q_UNUSED(previous)
if(nullptr != m_nextNode)
{
m_nextNode->run(this);
diff --git a/node/testnode.h b/tests/testnode.h
index 5c918ee..5c918ee 100644
--- a/node/testnode.h
+++ b/tests/testnode.h
diff --git a/tests/tst_dice.cpp b/tests/tst_dice.cpp
new file mode 100644
index 0000000..81618ca
--- /dev/null
+++ b/tests/tst_dice.cpp
@@ -0,0 +1,940 @@
+/***************************************************************************
+ * Copyright (C) 2011 by Renaud Guezennec *
+ * http://renaudguezennec.homelinux.org/accueil,3.html *
+ * *
+ * Rolisteam is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QString>
+#include <QtTest/QtTest>
+
+#include "dicealias.h"
+#include "diceparser.h"
+#include "die.h"
+
+// node
+#include "booleancondition.h"
+#include "node/bind.h"
+#include "node/countexecutenode.h"
+#include "node/explodedicenode.h"
+#include "node/filternode.h"
+#include "node/groupnode.h"
+#include "node/ifnode.h"
+#include "node/jumpbackwardnode.h"
+#include "node/keepdiceexecnode.h"
+#include "node/numbernode.h"
+#include "node/occurencecountnode.h"
+#include "node/rerolldicenode.h"
+#include "node/sortresult.h"
+#include "node/stringnode.h"
+#include "result/stringresult.h"
+#include "testnode.h"
+
+class TestDice : public QObject
+{
+ Q_OBJECT
+
+public:
+ TestDice();
+
+private slots:
+ void initTestCase();
+ void getAndSetTest();
+ void diceRollD10Test();
+ void diceRollD20Test();
+ void commandEndlessLoop();
+
+ void mathPriority();
+ void mathPriority_data();
+
+ void commandsTest();
+ void commandsTest_data();
+
+ void dangerousCommandsTest();
+ void dangerousCommandsTest_data();
+
+ void wrongCommandsTest();
+ void wrongCommandsTest_data();
+
+ void wrongCommandsExecutionTimeTest();
+ void scopeDF();
+ void scopeDF_data();
+
+ void severalInstruction();
+ void testAlias();
+ void cleanupTestCase();
+
+ void keepTest();
+ void keepTest_data();
+
+ void sortTest();
+ void sortTest_data();
+
+ void countTest();
+ void countTest_data();
+
+ void rerollTest();
+ void rerollTest_data();
+
+ void explodeTest();
+ void explodeTest_data();
+
+ void rerollUntilTest();
+ void rerollUntilTest_data();
+
+ void rerollAddTest();
+ void rerollAddTest_data();
+
+ void mergeTest();
+ void mergeTest_data();
+
+ void ifTest();
+ void ifTest_data();
+
+ void paintTest();
+ void paintTest_data();
+
+ void filterTest();
+ void filterTest_data();
+
+ void splitTest();
+ void splitTest_data();
+
+ void uniqueTest();
+ void uniqueTest_data();
+
+ void groupTest();
+ void groupTest_data();
+
+ void bindTest();
+ void bindTest_data();
+
+ void occurenceTest();
+ void occurenceTest_data();
+
+private:
+ std::unique_ptr<Die> m_die;
+ std::unique_ptr<DiceParser> m_diceParser;
+};
+
+TestDice::TestDice() {}
+
+void TestDice::initTestCase()
+{
+ m_die.reset(new Die());
+ m_diceParser.reset(new DiceParser());
+}
+
+void TestDice::getAndSetTest()
+{
+ for(unsigned int i= 0; i < 2000; i++)
+ {
+ m_die->setMaxValue(i);
+ QVERIFY(m_die->getMaxValue() == i);
+ }
+
+ m_die->setSelected(true);
+ QVERIFY(m_die->isSelected() == true);
+
+ m_die->setSelected(false);
+ QVERIFY(m_die->isSelected() == false);
+}
+
+void TestDice::diceRollD10Test()
+{
+ m_die->setMaxValue(10);
+ for(int i= 0; i < 2000; i++)
+ {
+ m_die->roll(false);
+ QVERIFY(m_die->getValue() > 0);
+ QVERIFY(m_die->getValue() < 11);
+ }
+}
+void TestDice::diceRollD20Test()
+{
+ m_die->setMaxValue(20);
+ for(int i= 0; i < 2000; i++)
+ {
+ m_die->roll(false);
+ QVERIFY(m_die->getValue() > 0);
+ QVERIFY(m_die->getValue() < 21);
+ }
+}
+void TestDice::commandEndlessLoop()
+{
+ bool a= m_diceParser->parseLine("1D10e[>0]");
+ QVERIFY(!a);
+}
+
+void TestDice::commandsTest()
+{
+ QFETCH(QString, cmd);
+
+ bool a= m_diceParser->parseLine(cmd);
+ QVERIFY2(a, "parsing");
+
+ m_diceParser->start();
+ QVERIFY2(m_diceParser->humanReadableError().isEmpty(), "no error");
+ QVERIFY2(m_diceParser->humanReadableWarning().isEmpty(), "no warning");
+}
+
+void TestDice::commandsTest_data()
+{
+ QTest::addColumn<QString>("cmd");
+
+ QTest::addRow("cmd1") << "1L[cheminée,chocolat,épée,arc,chute de pierre]";
+ QTest::addRow("cmd2") << "10d10c[>=6]-@c[=1]";
+ QTest::addRow("cmd3") << "10d10c[>=6]-@c[=1]-@c[=1]";
+ QTest::addRow("cmd4") << "10d10c[>6]+@c[=10]";
+ QTest::addRow("cmd5") << "1+1D10";
+ QTest::addRow("cmd6") << "3d10c[>=5]";
+ QTest::addRow("cmd7") << "1+(4*3)D10";
+ QTest::addRow("cmd8") << "2+4/4";
+ QTest::addRow("cmd9") << "2D10*2D20*8";
+ QTest::addRow("cmd10") << "1+(4*3)D10";
+ QTest::addRow("cmd11") << "(4D6)D10";
+ QTest::addRow("cmd12") << "1D100a[>=95]a[>=96]a[>=97]a[>=98]a[>=99]e[>=100]";
+ QTest::addRow("cmd13") << "3D100";
+ QTest::addRow("cmd14") << "4k3";
+ QTest::addRow("cmd15") << "10D10e[>=6]sc[>=6]";
+ QTest::addRow("cmd16") << "10D10e10s";
+ QTest::addRow("cmd17") << "10D10s";
+ QTest::addRow("cmd18") << "15D10e10c[8-10]";
+ QTest::addRow("cmd19") << "10d10e10";
+ QTest::addRow("cmd30") << "(4+4)^4";
+ QTest::addRow("cmd31") << "(1d20+20)*7/10";
+ QTest::addRow("cmd32") << "20*7/10";
+ QTest::addRow("cmd33") << "1D8+2D6+7";
+ QTest::addRow("cmd34") << "D25";
+ QTest::addRow("cmd35") << "1L[tete[10],ventre[50],jambe[40]]";
+ QTest::addRow("cmd36") << "2d6c[%2=0]";
+ QTest::addRow("cmd37") << "D25+D10";
+ QTest::addRow("cmd38") << "D25;D10";
+ QTest::addRow("cmd39") << "8+8+8";
+ QTest::addRow("cmd40") << "1D20-88";
+ QTest::addRow("cmd41") << "100*1D20*2D6";
+ QTest::addRow("cmd42") << "2D6 # two 6sided dice";
+ QTest::addRow("cmd43") << "100/28*3";
+ QTest::addRow("cmd44") << "100/8";
+ QTest::addRow("cmd45") << "100*3*8";
+ QTest::addRow("cmd46") << "help";
+ QTest::addRow("cmd47") << "la";
+ QTest::addRow("cmd48") << "10D10c[<2|>7]";
+ QTest::addRow("cmd49") << "10D6c[=2|=4|=6]";
+ QTest::addRow("cmd50") << "10D10e[=1|=10]k4";
+ QTest::addRow("cmd51") << "1L[tete,bras droit,bras gauche,jambe droite,jambe gauche,ventre[6-7],buste[8-10]]";
+ QTest::addRow("cmd52") << "10+10s";
+ QTest::addRow("cmd53") << "1d6e6;1d4e4mk1";
+ QTest::addRow("cmd54") << "1d6e6;1d4e4mk1";
+ QTest::addRow("cmd55") << "400D20/400000";
+ QTest::addRow("cmd56") << "1d100e[>=95]i[<5]{-1d100e95}";
+ QTest::addRow("cmd57") << "100*3*8";
+ QTest::addRow("cmd58") << "1d100i[<70]{1d10i[=10]{1d100i[<70]{1d10e10}}}";
+ QTest::addRow("cmd59") << "10d6c[<2|>5]";
+ QTest::addRow("cmd60") << "5-5*5+5";
+ QTest::addRow("cmd61") << "((3+4)*2)d6";
+ QTest::addRow("cmd62") << "4d6i[=6]{+1d6}";
+ QTest::addRow("cmd63") << "10d[-8--1]";
+ QTest::addRow("cmd64") << "4d6e6i[=4]{-4}+2";
+ QTest::addRow("cmd65") << "4d6e6f[!=4]+2";
+ QTest::addRow("cmd66") << "5d10g10";
+ QTest::addRow("cmd67") << "4d6p[4:blue]c[>=4];1d6p[1:#FFFFFF]c6-@c1;1d6p[1:#FF0000]c[>=4]+@c6-@c1";
+ QTest::addRow("cmd68") << "10d[0-9]";
+ QTest::addRow("cmd69") << "1d8e8;1d6e6mk1+2";
+ QTest::addRow("cmd70") << "3d100g50";
+ QTest::addRow("cmd71") << "3d100g33";
+ QTest::addRow("cmd72") << "3d100g5";
+ QTest::addRow("cmd73") << "3d100g40";
+ QTest::addRow("cmd74") << "2d10k1+2d10k1+2d10k1";
+ QTest::addRow("cmd75") << "2d10k1-2d10k1-2d10k1";
+ QTest::addRow("cmd76") << "(2d10k1)-2d10k1-2d10k1";
+ QTest::addRow("cmd77") << "2d10k1-(2d10k1)-2d10k1";
+ QTest::addRow("cmd78") << "2d10k1-2d10k1-(2d10k1)";
+ QTest::addRow("cmd79") << "1d6-2d6e6";
+ QTest::addRow("cmd80") << "(1)-1d6e6";
+ QTest::addRow("cmd81") << "(1)-(1d6e6)";
+ QTest::addRow("cmd82") << "8d10o";
+ QTest::addRow("cmd83") << "8d10o2,4";
+ QTest::addRow("cmd84") << "8d10o2[>2]";
+ QTest::addRow("cmd85") << "8d10ok2";
+ QTest::addRow("cmd86") << "[100,200,300]k2";
+ QTest::addRow("cmd87") << "100;200;300;[$1,$2,$3]k2";
+}
+
+void TestDice::wrongCommandsTest()
+{
+ // << "pajaejlbnmàw";
+ QFETCH(QString, cmd);
+ QFETCH(bool, valid);
+ bool a= m_diceParser->parseLine(cmd);
+ if(a)
+ {
+ m_diceParser->start();
+ auto map= m_diceParser->getErrorMap();
+ a= map.isEmpty();
+ }
+ QCOMPARE(a, valid);
+}
+
+void TestDice::wrongCommandsTest_data()
+{
+ QTest::addColumn<QString>("cmd");
+ QTest::addColumn<bool>("valid");
+
+ QTest::newRow("test1") << "1L[cheminée,chocolat,épée,arc,chute de pierre" << false;
+ QTest::newRow("test2") << "10d10c" << false;
+ QTest::newRow("test3") << "10d10a" << false;
+ QTest::newRow("test4") << "10d0a[>7]" << false;
+ QTest::newRow("test5") << "aiteanetauearuteurn" << false;
+ QTest::newRow("test6") << "meregue" << false;
+ QTest::newRow("test7") << "p i follow rivers" << false;
+ QTest::newRow("test8") << "manga violet evergarden" << false;
+ QTest::newRow("test9") << "((1d8e8+2);(1d6e6+2))" << true;
+}
+
+void TestDice::wrongCommandsExecutionTimeTest()
+{
+ QStringList commands;
+
+ //<< "8D20+10*@c[=20]"
+ commands << "1/0"
+ << ""
+ << "0d10"
+ << "10d10k11"
+ << "!!!!";
+
+ for(QString cmd : commands)
+ {
+ bool test= m_diceParser->parseLine(cmd);
+ m_diceParser->start();
+
+ QVERIFY2(m_diceParser->getErrorMap().isEmpty() == false || !test, cmd.toStdString().c_str());
+ }
+}
+void TestDice::scopeDF()
+{
+ QFETCH(QString, cmd);
+ QFETCH(int, min);
+ QFETCH(int, max);
+ QFETCH(bool, valid);
+
+ bool test= m_diceParser->parseLine(cmd);
+ QVERIFY2(test == valid, cmd.toStdString().c_str());
+ m_diceParser->start();
+ auto results= m_diceParser->getLastIntegerResults();
+
+ for(auto result : results)
+ QVERIFY(result >= min && result <= max);
+}
+
+void TestDice::scopeDF_data()
+{
+ QTest::addColumn<QString>("cmd");
+ QTest::addColumn<int>("min");
+ QTest::addColumn<int>("max");
+ QTest::addColumn<bool>("valid");
+
+ QTest::newRow("test1") << "1D[-1-1]" << -1 << 1 << true;
+ QTest::newRow("test2") << "1D[-10--5]" << -10 << -5 << true;
+ QTest::newRow("test3") << "1D[-100-100]" << -100 << 100 << true;
+ QTest::newRow("test4") << "1D[-1-0]" << -1 << 0 << true;
+ QTest::newRow("test5") << "1D[10-20]" << 10 << 20 << true;
+ QTest::newRow("test6") << "1D[30-100]" << 30 << 100 << true;
+ QTest::newRow("test7") << "1D[0-99]" << 0 << 99 << true;
+ QTest::newRow("test8") << "5-5*5+5" << -15 << -15 << true;
+ QTest::newRow("test9") << "2d20c[<=13]+@c[<=3]" << 0 << 4 << true;
+ QTest::newRow("test10") << "6d10c[>=6]-@c1" << -6 << 6 << true;
+ QTest::newRow("test11") << "2d6k1+2d8k1+2d10k1" << 3 << 30 << true;
+ QTest::newRow("test12") << "1D[-2-50]" << -2 << 50 << true;
+}
+void TestDice::testAlias()
+{
+ m_diceParser->insertAlias(new DiceAlias("!", "3d6c"), 0);
+ m_diceParser->insertAlias(new DiceAlias("g", "d10k"), 1);
+ m_diceParser->insertAlias(new DiceAlias("(.*)C(.*)", QStringLiteral("\\1d10e10c[>=\\2]"), false), 2);
+
+ QStringList cmds;
+ cmds << "!2"
+ << "${rang}g4"
+ << "${rang}g4 # gerald"
+ << "5C3"
+ << "1d100i:[<101]{\"great!\"}{\"try again\"}";
+
+ QStringList expected;
+ expected << "3d6c2"
+ << "${rang}d10k4"
+ << "${rang}d10k4 # gerald"
+ << "5d10e10c[>=3]"
+ << "1d100i:[<101]{\"great!\"}{\"try again\"}";
+
+ int i= 0;
+ for(auto cmd : cmds)
+ {
+ auto result= m_diceParser->convertAlias(cmd);
+ QVERIFY2(result == expected[i], result.toLatin1());
+ ++i;
+ }
+}
+void TestDice::severalInstruction()
+{
+ QStringList commands;
+
+ commands << "1d10;2d20;$1+$2";
+
+ QList<int> results;
+ results << 3;
+
+ int i= 0;
+ for(auto cmd : commands)
+ {
+ auto test= m_diceParser->parseLine(cmd);
+ QVERIFY2(test, cmd.toStdString().c_str());
+ QVERIFY2(m_diceParser->getStartNodeCount() == results[i], "Wrong number of instruction");
+ }
+}
+void TestDice::mathPriority()
+{
+ QFETCH(QString, cmd);
+ QFETCH(int, expected);
+
+ bool test= m_diceParser->parseLine(cmd);
+ QVERIFY(test);
+ m_diceParser->start();
+ auto resultList= m_diceParser->getLastIntegerResults();
+ QCOMPARE(resultList.size(), 1);
+
+ auto value= resultList.first();
+ QVERIFY(qFuzzyCompare(value, expected) == 1);
+}
+
+void TestDice::mathPriority_data()
+{
+ QTest::addColumn<QString>("cmd");
+ QTest::addColumn<int>("expected");
+
+ QTest::addRow("cmd1") << "10+2" << 12;
+ QTest::addRow("cmd2") << "2-10" << -8;
+ QTest::addRow("cmd3") << "5+2*3" << 11;
+ QTest::addRow("cmd4") << "5-5*5+5" << -15;
+ QTest::addRow("cmd5") << "5-5/5+5" << 9;
+ QTest::addRow("cmd6") << "10*(3*2)" << 60;
+ QTest::addRow("cmd7") << "60/(3*2)" << 10;
+ QTest::addRow("cmd8") << "5-(5*5+5)" << -25;
+}
+
+void TestDice::dangerousCommandsTest()
+{
+ QFETCH(QString, cmd);
+
+ for(int i= 0; i < 1000; ++i)
+ {
+ auto b= m_diceParser->parseLine(cmd);
+ QVERIFY(b);
+ m_diceParser->start();
+ }
+}
+void TestDice::dangerousCommandsTest_data()
+{
+ QTest::addColumn<QString>("cmd");
+
+ QTest::addRow("cmd1") << "10d6g10";
+ QTest::addRow("cmd2") << "10d2g10";
+ QTest::addRow("cmd3") << "10d10g10";
+ // QTest::addRow("cmd4") << "10d10g10";
+ // QTest::addRow("cmd5") << "10d10g10";
+}
+
+void makeResult(DiceResult& result, const QVector<int>& values)
+{
+ for(int val : values)
+ {
+ auto die= new Die();
+ die->setBase(1);
+ die->setMaxValue(10);
+ die->insertRollValue(val);
+ result.insertResult(die);
+ }
+}
+
+Validator* makeValidator(int number, BooleanCondition::LogicOperator op)
+{
+ BooleanCondition* validator= new BooleanCondition();
+ NumberNode* node= new NumberNode();
+ node->setNumber(number);
+ validator->setValueNode(node);
+ validator->setOperator(op);
+ return validator;
+}
+
+void TestDice::keepTest()
+{
+ QFETCH(QVector<int>, values);
+ QFETCH(int, keep);
+ QFETCH(int, score);
+ QFETCH(bool, error);
+
+ TestNode node;
+ KeepDiceExecNode keepN;
+ keepN.setDiceKeepNumber(keep);
+
+ DiceResult result;
+
+ makeResult(result, values);
+
+ node.setResult(&result);
+ node.setNextNode(&keepN);
+
+ node.run(nullptr);
+
+ bool isErrorEmpty= !keepN.getExecutionErrorMap().isEmpty();
+
+ QCOMPARE(isErrorEmpty, error);
+
+ if(error)
+ return;
+
+ auto resultScore= keepN.getResult()->getResult(Result::SCALAR).toInt();
+
+ QCOMPARE(score, resultScore);
+}
+
+void TestDice::keepTest_data()
+{
+ QTest::addColumn<QVector<int>>("values");
+ QTest::addColumn<int>("keep");
+ QTest::addColumn<int>("score");
+ QTest::addColumn<bool>("error");
+
+ QTest::addRow("cmd1") << QVector<int>({10, 9, 2}) << 1 << 10 << false;
+ QTest::addRow("cmd2") << QVector<int>({10, 9, 2}) << 2 << 19 << false;
+ QTest::addRow("cmd3") << QVector<int>({10, 9, 2}) << 3 << 21 << false;
+ QTest::addRow("cmd4") << QVector<int>({10, 9, 2}) << 4 << 0 << true;
+}
+
+void TestDice::sortTest()
+{
+ QFETCH(QVector<int>, values);
+ QFETCH(bool, ascending);
+ QFETCH(QVector<int>, scores);
+
+ TestNode node;
+ SortResultNode sortN;
+ sortN.setSortAscending(ascending);
+
+ DiceResult result;
+
+ makeResult(result, values);
+
+ node.setResult(&result);
+ node.setNextNode(&sortN);
+
+ DiceResult expectedScore;
+ makeResult(expectedScore, scores);
+
+ node.run(nullptr);
+
+ auto list= dynamic_cast<DiceResult*>(sortN.getResult())->getResultList();
+
+ int i= 0;
+ auto expected= expectedScore.getResultList();
+ for(auto sortedDie : list)
+ {
+ QCOMPARE(expected[i]->getValue(), sortedDie->getValue());
+ ++i;
+ }
+}
+
+void TestDice::sortTest_data()
+{
+ QTest::addColumn<QVector<int>>("values");
+ QTest::addColumn<bool>("ascending");
+ QTest::addColumn<QVector<int>>("scores");
+
+ QTest::addRow("cmd1") << QVector<int>({10, 9, 2}) << true << QVector<int>({2, 9, 10});
+ QTest::addRow("cmd2") << QVector<int>({1, 2, 3}) << false << QVector<int>({3, 2, 1});
+ QTest::addRow("cmd3") << QVector<int>({10, 9, 2}) << false << QVector<int>({10, 9, 2});
+ QTest::addRow("cmd4") << QVector<int>({2, 9, 10}) << true << QVector<int>({2, 9, 10});
+ QTest::addRow("cmd5") << QVector<int>({1, 25, 10}) << false << QVector<int>({25, 10, 1});
+ QTest::addRow("cmd6") << QVector<int>({10, 2, 100}) << false << QVector<int>({100, 10, 2});
+}
+
+void TestDice::countTest()
+{
+ QFETCH(QVector<int>, values);
+ QFETCH(int, condition);
+ QFETCH(int, score);
+
+ TestNode node;
+ CountExecuteNode countN;
+
+ auto validator= makeValidator(condition, BooleanCondition::GreaterThan);
+
+ countN.setValidator(validator);
+ DiceResult result;
+ node.setResult(&result);
+ node.setNextNode(&countN);
+
+ makeResult(result, values);
+
+ node.run(nullptr);
+
+ QCOMPARE(score, countN.getResult()->getResult(Result::SCALAR).toInt());
+
+ countN.setValidator(nullptr);
+}
+
+void TestDice::countTest_data()
+{
+ QTest::addColumn<QVector<int>>("values");
+ QTest::addColumn<int>("condition");
+ QTest::addColumn<int>("score");
+
+ QTest::addRow("cmd1") << QVector<int>({10, 9, 2}) << 3 << 2;
+ QTest::addRow("cmd2") << QVector<int>({1, 2, 3}) << 3 << 0;
+}
+
+void TestDice::rerollTest()
+{
+ QFETCH(QVector<int>, values);
+ QFETCH(int, condition);
+ QFETCH(bool, different);
+
+ TestNode node;
+ RerollDiceNode reroll(true, false);
+
+ DiceResult result;
+ makeResult(result, values);
+ node.setResult(&result);
+
+ auto validator= makeValidator(condition, BooleanCondition::GreaterThan);
+ reroll.setValidator(validator);
+ node.setNextNode(&reroll);
+
+ node.run(nullptr);
+
+ auto list= dynamic_cast<DiceResult*>(reroll.getResult())->getResultList();
+
+ int i= 0;
+ auto expected= result.getResultList();
+ bool resultDiff= false;
+ for(auto rerolled : list)
+ {
+ if(!resultDiff && rerolled->getValue() != expected[i]->getValue())
+ resultDiff= true;
+ ++i;
+ }
+
+ QCOMPARE(different, resultDiff);
+}
+
+void TestDice::rerollTest_data()
+{
+ QTest::addColumn<QVector<int>>("values");
+ QTest::addColumn<int>("condition");
+ QTest::addColumn<bool>("different");
+
+ QTest::addRow("cmd1") << QVector<int>({8, 9, 2}) << 10 << false;
+ QTest::addRow("cmd2") << QVector<int>({0, 0, 0}) << -1 << true;
+}
+
+void TestDice::explodeTest()
+{
+ QFETCH(QVector<int>, values);
+ QFETCH(int, condition);
+ QFETCH(bool, different);
+
+ TestNode node;
+ ExplodeDiceNode explode;
+
+ DiceResult result;
+ makeResult(result, values);
+ node.setResult(&result);
+
+ auto validator= makeValidator(condition, BooleanCondition::Equal);
+ explode.setValidator(validator);
+ node.setNextNode(&explode);
+
+ node.run(nullptr);
+
+ auto list= dynamic_cast<DiceResult*>(explode.getResult())->getResultList();
+
+ int i= 0;
+ auto expected= result.getResultList();
+ bool resultDiff= false;
+ for(auto rerolled : list)
+ {
+ if(!resultDiff && rerolled->getValue() != expected[i]->getValue())
+ resultDiff= true;
+ ++i;
+ }
+
+ QCOMPARE(different, resultDiff);
+}
+
+void TestDice::explodeTest_data()
+{
+ QTest::addColumn<QVector<int>>("values");
+ QTest::addColumn<int>("condition");
+ QTest::addColumn<bool>("different");
+
+ QTest::addRow("cmd1") << QVector<int>({8, 9, 2}) << 10 << false;
+ QTest::addRow("cmd2") << QVector<int>({0, 0, 0}) << 0 << true;
+}
+
+void TestDice::rerollUntilTest()
+{
+ QFETCH(QVector<int>, values);
+ QFETCH(int, condition);
+ QFETCH(bool, different);
+
+ TestNode node;
+ RerollDiceNode reroll(false, false);
+
+ DiceResult result;
+ makeResult(result, values);
+ node.setResult(&result);
+
+ auto validator= makeValidator(condition, BooleanCondition::Equal);
+ reroll.setValidator(validator);
+ node.setNextNode(&reroll);
+
+ node.run(nullptr);
+
+ auto list= dynamic_cast<DiceResult*>(reroll.getResult())->getResultList();
+
+ int i= 0;
+ auto expected= result.getResultList();
+ bool resultDiff= false;
+ for(auto rerolled : list)
+ {
+ if(!resultDiff && rerolled->getValue() != expected[i]->getValue())
+ resultDiff= true;
+ ++i;
+ }
+
+ QCOMPARE(different, resultDiff);
+}
+void TestDice::rerollUntilTest_data()
+{
+ QTest::addColumn<QVector<int>>("values");
+ QTest::addColumn<int>("condition");
+ QTest::addColumn<bool>("different");
+
+ QTest::addRow("cmd1") << QVector<int>({8, 9, 2}) << 10 << false;
+ QTest::addRow("cmd2") << QVector<int>({0, 0, 0}) << 0 << true;
+}
+
+void TestDice::rerollAddTest()
+{
+ QFETCH(QVector<int>, values);
+ QFETCH(int, condition);
+ QFETCH(bool, different);
+
+ TestNode node;
+ RerollDiceNode reroll(true, true);
+
+ DiceResult result;
+ makeResult(result, values);
+ node.setResult(&result);
+
+ auto validator= makeValidator(condition, BooleanCondition::Equal);
+ reroll.setValidator(validator);
+ node.setNextNode(&reroll);
+
+ node.run(nullptr);
+
+ auto list= dynamic_cast<DiceResult*>(reroll.getResult())->getResultList();
+
+ int i= 0;
+ auto expected= result.getResultList();
+ bool resultDiff= false;
+ for(auto rerolled : list)
+ {
+ if(!resultDiff && rerolled->getValue() != expected[i]->getValue())
+ resultDiff= true;
+ ++i;
+ }
+
+ QCOMPARE(different, resultDiff);
+}
+void TestDice::rerollAddTest_data()
+{
+ QTest::addColumn<QVector<int>>("values");
+ QTest::addColumn<int>("condition");
+ QTest::addColumn<bool>("different");
+
+ QTest::addRow("cmd1") << QVector<int>({8, 9, 2}) << 10 << false;
+ QTest::addRow("cmd2") << QVector<int>({0, 0, 0}) << 0 << true;
+}
+
+void TestDice::mergeTest() {}
+void TestDice::mergeTest_data() {}
+
+void TestDice::ifTest()
+{
+ QFETCH(QVector<int>, values);
+ QFETCH(int, condition);
+ QFETCH(int, valCondition);
+ QFETCH(QString, expectedResult);
+
+ IfNode::ConditionType conditionType= static_cast<IfNode::ConditionType>(condition);
+
+ TestNode node;
+ IfNode ifNode;
+ ifNode.setConditionType(conditionType);
+
+ DiceResult result;
+ makeResult(result, values);
+ node.setResult(&result);
+
+ StringNode trueNode;
+ trueNode.setString(QStringLiteral("True"));
+ StringNode falseNode;
+ falseNode.setString(QStringLiteral("False"));
+
+ ifNode.setInstructionTrue(&trueNode);
+ ifNode.setInstructionFalse(&falseNode);
+
+ auto validator= makeValidator(valCondition, BooleanCondition::Equal);
+ ifNode.setValidator(validator);
+ node.setNextNode(&ifNode);
+
+ node.run(nullptr);
+
+ auto text= dynamic_cast<StringResult*>(ifNode.getNextNode()->getResult())->getText();
+
+ QCOMPARE(expectedResult, text);
+
+ ifNode.setNextNode(nullptr);
+}
+void TestDice::ifTest_data()
+{
+ QTest::addColumn<QVector<int>>("values");
+ QTest::addColumn<int>("condition");
+ QTest::addColumn<int>("valCondition");
+ QTest::addColumn<QString>("expectedResult");
+
+ int onEach= 0;
+ int oneOfThem= 1;
+ int allOfThem= 2;
+ int onScalar= 3;
+
+ QTest::addRow("cmd1") << QVector<int>({8, 9, 2}) << onEach << 0 << "False";
+ QTest::addRow("cmd2") << QVector<int>({2, 2, 2}) << onEach << 2 << "True";
+
+ QTest::addRow("cmd3") << QVector<int>({0, 0, 0}) << oneOfThem << 10 << "False";
+ QTest::addRow("cmd4") << QVector<int>({10, 9, 5}) << oneOfThem << 10 << "True";
+ QTest::addRow("cmd5") << QVector<int>({9, 9, 9}) << oneOfThem << 9 << "True";
+
+ QTest::addRow("cmd6") << QVector<int>({8, 9, 2}) << allOfThem << 1 << "False";
+ QTest::addRow("cmd7") << QVector<int>({8, 9, 2}) << allOfThem << 9 << "False";
+ QTest::addRow("cmd8") << QVector<int>({8, 8, 8}) << allOfThem << 8 << "True";
+
+ QTest::addRow("cmd9") << QVector<int>({25, 8, 14}) << onScalar << 1 << "False";
+ QTest::addRow("cmd10") << QVector<int>({25, 8, 14}) << onScalar << 47 << "True";
+}
+
+void TestDice::paintTest() {}
+void TestDice::paintTest_data() {}
+
+void TestDice::filterTest()
+{
+ QFETCH(QVector<int>, values);
+ QFETCH(int, condition);
+ QFETCH(bool, different);
+
+ TestNode node;
+ FilterNode filter;
+
+ DiceResult result;
+ makeResult(result, values);
+ node.setResult(&result);
+
+ auto validator= makeValidator(condition, BooleanCondition::Different);
+ filter.setValidator(validator);
+ node.setNextNode(&filter);
+
+ node.run(nullptr);
+
+ auto list= dynamic_cast<DiceResult*>(filter.getResult())->getResultList();
+
+ auto expected= result.getResultList();
+ bool resultDiff= (list.size() != expected.size());
+
+ QCOMPARE(different, resultDiff);
+}
+
+void TestDice::filterTest_data()
+{
+ QTest::addColumn<QVector<int>>("values");
+ QTest::addColumn<int>("condition");
+ QTest::addColumn<bool>("different");
+
+ QTest::addRow("cmd1") << QVector<int>({8, 4, 2}) << 4 << true;
+ QTest::addRow("cmd2") << QVector<int>({0, 0, 0}) << 1 << false;
+}
+
+void TestDice::splitTest() {}
+void TestDice::splitTest_data() {}
+
+void TestDice::uniqueTest() {}
+void TestDice::uniqueTest_data() {}
+
+void TestDice::groupTest() {}
+void TestDice::groupTest_data() {}
+
+void TestDice::bindTest() {}
+void TestDice::bindTest_data() {}
+
+void TestDice::occurenceTest()
+{
+ QFETCH(QVector<int>, values);
+ QFETCH(int, condition);
+ QFETCH(QString, expected);
+
+ TestNode node;
+ OccurenceCountNode count;
+
+ DiceResult result;
+ makeResult(result, values);
+ node.setResult(&result);
+
+ auto validator= makeValidator(condition, BooleanCondition::GreaterThan);
+ count.setValidator(validator);
+ node.setNextNode(&count);
+
+ node.run(nullptr);
+
+ auto text= dynamic_cast<StringResult*>(count.getResult())->getText();
+
+ QVERIFY(text.startsWith(expected));
+}
+void TestDice::occurenceTest_data()
+{
+ QTest::addColumn<QVector<int>>("values");
+ QTest::addColumn<int>("condition");
+ QTest::addColumn<QString>("expected");
+
+ QTest::addRow("cmd1") << QVector<int>({8, 8, 2}) << 7 << "2x8";
+ QTest::addRow("cmd2") << QVector<int>({0, 0, 0}) << 1 << "No matching result";
+}
+
+void TestDice::cleanupTestCase() {}
+
+QTEST_MAIN(TestDice)
+
+#include "tst_dice.moc"