diff options
Diffstat (limited to 'tests/unit/SpacedRepetitionModel/SRModel_pickCard_test.cpp')
-rw-r--r-- | tests/unit/SpacedRepetitionModel/SRModel_pickCard_test.cpp | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/tests/unit/SpacedRepetitionModel/SRModel_pickCard_test.cpp b/tests/unit/SpacedRepetitionModel/SRModel_pickCard_test.cpp new file mode 100644 index 0000000..73ab023 --- /dev/null +++ b/tests/unit/SpacedRepetitionModel/SRModel_pickCard_test.cpp @@ -0,0 +1,420 @@ +#include "SRModel_pickCard_test.h" +#include "../../common/printQtTypes.h" +#include "../../../src/dictionary/Card.h" +#include "../../mocks/RandomGenerator_mock.h" +#include "../../../src/utils/TimeProvider.h" + +static const StudySettings* ss = StudySettings::inst(); + +const double SRModel_pickCard_Test::HourAgo = -1. / 24; + +void SRModel_pickCard_Test::SetUp() +{ + randomGenerator->setRand(1); +} + +// Time interval + +TEST_F(SRModel_pickCard_Test, pick_active1) +{ + addStudied(-1, 1); + testPicked({0}); +} + +TEST_F(SRModel_pickCard_Test, pick_active2) +{ + addStudied(-8.5, 8.1); + testPicked({0}); +} + +TEST_F(SRModel_pickCard_Test, pick_active_and_future) +{ + addStudied(-1, 1); + addStudied(-1, 2); + testPicked({0}); +} + +TEST_F(SRModel_pickCard_Test, pick_2active1) +{ + addStudied(-1, 1); + addStudied(-1.1, 1); + + randomGenerator->setRand(0); + testPicked({0}); +} + +TEST_F(SRModel_pickCard_Test, pick_2active2) +{ + addStudied(-1, 1); + addStudied(-1.1, 1); + testPicked({1, 0}); +} + +TEST_F(SRModel_pickCard_Test, pick_3active) +{ + addStudied(-1, 1); + addStudied(-1.1, 1); + addStudied(-1.2, 1); + testPicked({1, 2, 0}); +} + +TEST_F(SRModel_pickCard_Test, pick_future1) +{ + addStudied(-1, 2); + testPicked({NoCard}); +} + +TEST_F(SRModel_pickCard_Test, pick_future2) +{ + addStudied(-1, 2); + addStudied(-1.1, 2); + testPicked({NoCard}); +} + + +// Priority cards with small intervals +// Always pick first cards with small interval + +TEST_F(SRModel_pickCard_Test, pick_zeroInterval) // Unreal +{ + addStudied(HourAgo, 0); + testPicked({0}); +} + +TEST_F(SRModel_pickCard_Test, pick_unknown) +{ + addUnknown(HourAgo); + testPicked({0}); +} + +TEST_F(SRModel_pickCard_Test, pick_unknown_and_active) +{ + addUnknown(HourAgo); + addStudied(-1, 1); + testPicked({0, 1}); +} + +TEST_F(SRModel_pickCard_Test, pick_learning3min_and_active) +{ + addLearning(-3./(24*60)); // 3 min back + addStudied(-1, 1); + testPicked({1, 0}); +} + +TEST_F(SRModel_pickCard_Test, pick_learning10min_and_active) +{ + addLearning(-10./(24*60)); + addStudied(-1, 1); + testPicked({0, 1}); +} + +TEST_F(SRModel_pickCard_Test, pick_learningPrevDay_and_active) +{ + addLearning(-1); + addStudied(-1, 1); + testPicked({0, 1}); +} + +TEST_F(SRModel_pickCard_Test, pick_unknown_and_2actives) +{ + addUnknown(HourAgo); + addStudied(-1, 1); + addStudied(-1.1, 1); + testPicked({0, 2, 1}); +} + +TEST_F(SRModel_pickCard_Test, pick_remembered_and_2actives) +{ + addStudied(-1, ss->nextDayInterval); + addStudied(-1, 1); + addStudied(-1.1, 1); + testPicked({0, 2, 1}); +} + +TEST_F(SRModel_pickCard_Test, pick_competing_unknown_and_new) +{ + addUnknown(HourAgo); + addNew(); + addStudied(-1, 1); + testPicked({0, 1, 2}); +} + +TEST_F(SRModel_pickCard_Test, pick_competing_remembered_and_new) +{ + addStudied(-1, ss->nextDayInterval); + addNew(); + addStudied(-1, 1); + testPicked({0, 1, 2}); +} + +TEST_F(SRModel_pickCard_Test, pick_2unknowns_and_2actives) +{ + addUnknown(HourAgo); + addUnknown(2 * HourAgo); + addStudied(-1, 1); + addStudied(-1.1, 1); + testPicked({1, 0, 3, 2}); +} + +TEST_F(SRModel_pickCard_Test, pick_unknown_and_3actives) +{ + addUnknown(HourAgo); + addStudied(-1, 1); + addStudied(-1.1, 1); + addStudied(-1.2, 1); + testPicked({0, 2, 3, 1}); +} + +TEST_F(SRModel_pickCard_Test, pick_unknown_and_remembered) +{ + addUnknown(HourAgo); + addStudied(-1, ss->nextDayInterval); + addStudied(-1, 1); + testPicked({0, 1, 2}); +} + +TEST_F(SRModel_pickCard_Test, pick_incorrect_and_remembered) +{ + addIncorrect(HourAgo); + addStudied(-1, ss->nextDayInterval); + addStudied(-1, 1); + testPicked({0, 1, 2}); +} + +TEST_F(SRModel_pickCard_Test, pick_unknown_and_incorrect) +{ + addUnknown(HourAgo); + addIncorrect(HourAgo); + addStudied(-1, 1); + testPicked({0, 1, 2}); +} + +// New cards + +TEST_F(SRModel_pickCard_Test, pick_new) +{ + addNew(); + testPicked({0}); +} + +TEST_F(SRModel_pickCard_Test, pick_new_and_studied1) +{ + addNew(); + addStudied(-1.1, 1); + + randomGenerator->setDouble(0.3); // Pick studied first + testPicked({1, 0}); +} + +TEST_F(SRModel_pickCard_Test, pick_new_and_studied2) +{ + addNew(); + addStudied(-1.1, 1); + + // Pick new first + testPicked({0, 1}); +} + +TEST_F(SRModel_pickCard_Test, pick_2new) +{ + addNew(); + addNew(); + testPicked({1, 0}); +} + +TEST_F(SRModel_pickCard_Test, pick_3new) +{ + for(int i = 0; i < 3; i++) + addNew(); + testPicked({1, 2, 0}); +} + +TEST_F(SRModel_pickCard_Test, pick_2new_and_2studied1) +{ + addNew(); + addNew(); + addStudied(-1, 1); + addStudied(-1.1, 1); + + randomGenerator->setDouble(0.3); // Pick studied first + testPicked({3, 2, 1, 0}); +} + +TEST_F(SRModel_pickCard_Test, pick_2new_and_2studied2) +{ + addNew(); + addNew(); + addStudied(-1, 1); + addStudied(-1.1, 1); + + // Pick new first, double random = 0 + testPicked({1, 0, 3, 2}); +} + +TEST_F(SRModel_pickCard_Test, pick_2new_and_2studied3) +{ + addNew(); + addNew(); + addStudied(-1, 1); + addStudied(-1.1, 1); + + randomGenerator->setDouble(0.3); // Pick studied first + model.testPickCard(); + assertCurCard(3); + randomGenerator->setDouble(0.1); // Pick new first + model.scheduleCard(4); + assertCurCard(1); + randomGenerator->setDouble(0.3); + model.scheduleCard(4); + assertCurCard(2); + randomGenerator->setDouble(0.1); + model.scheduleCard(4); + assertCurCard(0); +} + +TEST_F(SRModel_pickCard_Test, pick_incorrect_new_and_studied) +{ + addIncorrect(HourAgo); + addNew(); + addStudied(-1, 1); + + randomGenerator->setDouble(0.3); // Pick studied first + testPicked({0, 2, 1}); +} + +TEST_F(SRModel_pickCard_Test, pick_newAndActive_newLimitReached) +{ + for(int i = 0; i < ss->newCardsDayLimit; i++) + addStudied(HourAgo, ss->nextDayInterval); + + addNew(); + addStudied(-1, 1); + + int studiedCard = ss->newCardsDayLimit + 1; + testPicked({studiedCard, NoCard}); +} + +TEST_F(SRModel_pickCard_Test, pick_2new_newLimitReached) +{ + for(int i = 0; i < ss->newCardsDayLimit; i++) + addStudied(HourAgo, ss->nextDayInterval); + + addNew(); + addNew(); + + testPicked({NoCard}); +} + +// Remaining incorrect cards +// Must be taken in the end (both active and new cards are finished) + +TEST_F(SRModel_pickCard_Test, pick_remaining_unknown) +{ + addUnknown(Now); + addStudied(-1, 1); + testPicked({1, 0}); +} + +TEST_F(SRModel_pickCard_Test, pick_remaining_incorrect) +{ + addIncorrect(Now); + addStudied(-1, 1); + testPicked({1, 0}); +} + +TEST_F(SRModel_pickCard_Test, pick_remaining_remembered) +{ + addStudied(Now, ss->nextDayInterval); + addStudied(-1, 1); + testPicked({1, NoCard}); +} + +TEST_F(SRModel_pickCard_Test, pick_remaining_unknownAndIncorrect) +{ + addIncorrect(HourAgo); + addUnknown(Now); + addStudied(-1, 1); + testPicked({0, 2, 1}); +} + +TEST_F(SRModel_pickCard_Test, pick_remaining_after_new) +{ + addNew(); + testPicked({0, 0, 0, NoCard}); +} + +TEST_F(SRModel_pickCard_Test, pick_remaining_after_2new) +{ + addNew(); + addNew(); + testPicked({1, 0, 1, 0, 1, 0, NoCard}); +} + + + +QDateTime SRModel_pickCard_Test::timeFromDelta(double daysDelta) +{ + return TimeProvider::get().addSecs((int)(daysDelta * 24 * 60 * 60)); +} + +void SRModel_pickCard_Test::addStudied(double daysDelta, double interval, + int grade, int level) +{ + QString name = addRecord(); + pack.generateQuestions(); + StudyRecord study(level, grade, 2.5, interval); + study.date = timeFromDelta(daysDelta); + pack.addStudyRecord(name, study); +} + +void SRModel_pickCard_Test::addUnknown(double daysDelta) +{ + addStudied(daysDelta, ss->unknownInterval, StudyRecord::Unknown, + StudyRecord::ShortLearning); +} + +void SRModel_pickCard_Test::addIncorrect(double daysDelta) +{ + addStudied(daysDelta, ss->incorrectInterval, StudyRecord::Incorrect, + StudyRecord::ShortLearning); +} + +void SRModel_pickCard_Test::addLearning(double daysDelta) +{ + addStudied(daysDelta, ss->learningInterval, StudyRecord::Good, + StudyRecord::LongLearning); +} + +void SRModel_pickCard_Test::addNew() +{ + addRecord(); + pack.generateQuestions(); +} + +void SRModel_pickCard_Test::assertCurCard(int expCard) +{ + if(expCard < 0) + { + ASSERT_FALSE(model.getCurCard()); + return; + } + ASSERT_TRUE(model.getCurCard()); + ASSERT_EQ(expCard, model.getCurCard()->getQuestion().toInt()); +} + +void SRModel_pickCard_Test::testPicked(const vector<int>& expCards) +{ + vector<int> pickedCards; + for(unsigned i = 0; i < expCards.size(); i++) + { + if(i == 0) + model.testPickCard(); + else + model.scheduleCard(StudyRecord::Good); + if(model.getCurCard()) + pickedCards.push_back(model.getCurCard()->getQuestion().toInt()); + else + pickedCards.push_back(-1); + } + ASSERT_EQ(expCards, pickedCards); +} |