#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& expCards) { vector 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); }