Warning, file /education/parley/src/practice/practicestatemachine.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2009-2010 Frederik Gladhorn <gladhorn@kde.org> 0003 SPDX-FileCopyrightText: 2009 Daniel Laidig <d.laidig@gmx.de> 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "practicestatemachine.h" 0008 0009 #include "parleydocument.h" 0010 0011 #include "comparisonbackendmode.h" 0012 #include "conjugationbackendmode.h" 0013 #include "examplesentencebackendmode.h" 0014 #include "flashcardbackendmode.h" 0015 #include "genderbackendmode.h" 0016 #include "multiplechoicebackendmode.h" 0017 #include "prefs.h" 0018 #include "writtenbackendmode.h" 0019 0020 using namespace Practice; 0021 0022 PracticeStateMachine::PracticeStateMachine(AbstractFrontend *frontend, ParleyDocument *doc, SessionManagerBase *sessionManager, QObject *parent) 0023 : QObject(parent) 0024 , m_frontend(frontend) 0025 , m_document(doc) 0026 , m_sessionManager(sessionManager) 0027 { 0028 createPracticeMode(); 0029 0030 // To allow to skip an an entry 0031 connect(m_frontend, &AbstractFrontend::skipAction, this, &PracticeStateMachine::nextEntry); 0032 connect(m_frontend, &AbstractFrontend::stopPractice, this, &PracticeStateMachine::slotPracticeFinished); 0033 connect(m_frontend, &AbstractFrontend::hintAction, m_mode, &AbstractBackendMode::hintAction); 0034 0035 connect(m_frontend, &AbstractFrontend::continueAction, this, &PracticeStateMachine::continueAction); 0036 0037 connect(m_mode, &AbstractBackendMode::answerRight, this, &PracticeStateMachine::answerRight); 0038 connect(m_mode, &AbstractBackendMode::answerWrongRetry, this, &PracticeStateMachine::answerWrongRetry); 0039 connect(m_mode, &AbstractBackendMode::answerWrongShowSolution, this, &PracticeStateMachine::answerWrongShowSolution); 0040 connect(m_mode, &AbstractBackendMode::showSolution, this, &PracticeStateMachine::showSolution); 0041 } 0042 0043 void PracticeStateMachine::createPracticeMode() 0044 { 0045 switch (Prefs::practiceMode()) { 0046 case Prefs::EnumPracticeMode::FlashCardsPractice: 0047 qDebug() << "Create Flash Card Practice backend"; 0048 m_frontend->setMode(AbstractFrontend::FlashCard); 0049 m_mode = new FlashCardBackendMode(m_frontend, this); 0050 break; 0051 case Prefs::EnumPracticeMode::MultipleChoicePractice: 0052 qDebug() << "Create MultipleChoice Practice backend"; 0053 m_frontend->setMode(AbstractFrontend::MultipleChoice); 0054 m_mode = new MultipleChoiceBackendMode(m_frontend, this, m_sessionManager); 0055 break; 0056 case Prefs::EnumPracticeMode::MixedLettersPractice: 0057 qDebug() << "Create Mixed Letters Practice backend"; 0058 m_frontend->setMode(AbstractFrontend::MixedLetters); 0059 m_mode = new WrittenBackendMode(m_frontend, this, m_sessionManager, m_document->document().get()); 0060 break; 0061 case Prefs::EnumPracticeMode::WrittenPractice: 0062 qDebug() << "Create Written Practice backend"; 0063 m_frontend->setMode(AbstractFrontend::Written); 0064 m_mode = new WrittenBackendMode(m_frontend, this, m_sessionManager, m_document->document().get()); 0065 break; 0066 case Prefs::EnumPracticeMode::ExampleSentencesPractice: 0067 qDebug() << "Create Written Practice backend"; 0068 m_frontend->setMode(AbstractFrontend::ExampleSentence); 0069 m_mode = new ExampleSentenceBackendMode(m_frontend, this, m_sessionManager, m_document->document().get()); 0070 break; 0071 case Prefs::EnumPracticeMode::GenderPractice: 0072 m_frontend->setMode(AbstractFrontend::MultipleChoice); 0073 m_mode = new GenderBackendMode(m_frontend, this, m_sessionManager, m_document->document().get()); 0074 break; 0075 case Prefs::EnumPracticeMode::ConjugationPractice: 0076 m_frontend->setMode(AbstractFrontend::Conjugation); 0077 m_mode = new ConjugationBackendMode(m_frontend, this, m_sessionManager, m_document->document().get()); 0078 break; 0079 case Prefs::EnumPracticeMode::ComparisonPractice: 0080 m_frontend->setMode(AbstractFrontend::Comparison); 0081 m_mode = new ComparisonBackendMode(m_frontend, this, m_sessionManager, m_document->document().get()); 0082 break; 0083 0084 default: 0085 Q_ASSERT("Implement selected practice mode" == 0); 0086 } 0087 } 0088 0089 void Practice::PracticeStateMachine::start() 0090 { 0091 qDebug() << "Start practice"; 0092 m_sessionManager->practiceStarted(); 0093 nextEntry(); 0094 } 0095 0096 void PracticeStateMachine::nextEntry() 0097 { 0098 m_state = NotAnswered; 0099 m_current = m_sessionManager->nextTrainingEntry(); 0100 0101 // qDebug() << "GETTING ENTRY - " << m_current; 0102 0103 // after going through all words, or at the start of practice 0104 if (m_current == 0) { 0105 slotPracticeFinished(); 0106 return; 0107 } 0108 if (!m_mode->setTestEntry(m_current)) { 0109 // this is just a fall back, if an invalid entry slipped through 0110 currentEntryFinished(); 0111 nextEntry(); 0112 } 0113 updateFrontend(); 0114 } 0115 0116 void PracticeStateMachine::slotPracticeFinished() 0117 { 0118 qDebug() << "Stop practice"; 0119 m_sessionManager->practiceFinished(); 0120 Q_EMIT practiceFinished(); 0121 } 0122 0123 void PracticeStateMachine::currentEntryFinished() 0124 { 0125 m_sessionManager->removeCurrentEntryFromPractice(); 0126 } 0127 0128 void PracticeStateMachine::continueAction() 0129 { 0130 // qDebug() << "continue" << m_state; 0131 switch (m_state) { 0132 // on continue, we check the answer, if in NotAnsweredState or AnswerWasWrongState 0133 case NotAnswered: 0134 case AnswerWasWrong: 0135 m_mode->checkAnswer(); 0136 break; 0137 0138 case SolutionShown: 0139 gradeEntryAndContinue(); 0140 break; 0141 } 0142 } 0143 0144 void PracticeStateMachine::answerRight() 0145 { 0146 // qDebug() << "ans right"; 0147 0148 m_frontend->setFeedbackState(AbstractFrontend::AnswerCorrect); 0149 if (m_state == NotAnswered) { 0150 m_frontend->setResultState(AbstractFrontend::AnswerCorrect); 0151 } else { 0152 m_frontend->setResultState(AbstractFrontend::AnswerWrong); 0153 } 0154 0155 m_state = SolutionShown; 0156 m_frontend->showSolution(); 0157 } 0158 0159 void PracticeStateMachine::answerWrongRetry() 0160 { 0161 // qDebug() << "wrong retr"; 0162 m_frontend->setFeedbackState(AbstractFrontend::AnswerWrong); 0163 m_state = AnswerWasWrong; 0164 } 0165 0166 void PracticeStateMachine::answerWrongShowSolution() 0167 { 0168 // qDebug() << "wrong sol"; 0169 m_frontend->setFeedbackState(AbstractFrontend::AnswerWrong); 0170 // User gave an empty answer or the same answer for a second time so we want to drop out. 0171 m_frontend->setResultState(AbstractFrontend::AnswerWrong); 0172 m_state = SolutionShown; 0173 m_frontend->showSolution(); 0174 } 0175 0176 void PracticeStateMachine::showSolution() 0177 { 0178 // qDebug() << "show solution"; 0179 m_state = SolutionShown; 0180 m_frontend->showSolution(); 0181 } 0182 0183 void PracticeStateMachine::updateFrontend() 0184 { 0185 m_frontend->setFeedbackState(AbstractFrontend::QuestionState); 0186 m_frontend->setResultState(AbstractFrontend::QuestionState); 0187 m_frontend->setLessonName(m_current->entry()->lesson()->name()); 0188 grade_t grade = m_mode->currentGradeForEntry(); 0189 m_frontend->showGrade(m_mode->currentPreGradeForEntry(), grade); 0190 0191 // show the word that is currently practiced in the progress bar 0192 m_frontend->setFinishedWordsTotalWords(m_sessionManager->allEntryCount() - m_sessionManager->activeEntryCount(), m_sessionManager->allEntryCount()); 0193 0194 // Set fonts 0195 m_frontend->setQuestionFont((m_current->languageFrom() == Prefs::learningLanguage()) ? m_frontend->learningLangFont() : m_frontend->knownLangFont()); 0196 m_frontend->setSolutionFont((m_current->languageTo() == Prefs::learningLanguage()) ? m_frontend->learningLangFont() : m_frontend->knownLangFont()); 0197 0198 grade_t goodGrade = qMax(grade, grade_t(KV_LEV1_GRADE)); // if the word hasn't been practiced yet, use grade 1 as a base 0199 0200 if (m_current->statisticBadCount() == 0) { 0201 goodGrade = qMax(KV_LEV2_GRADE, qMin(grade + 1, KV_MAX_GRADE)); 0202 } 0203 0204 m_frontend->setBoxes(grade, goodGrade, KV_LEV1_GRADE); 0205 0206 QUrl imgFrom = m_current->entry()->translation(m_current->languageFrom())->imageUrl(); 0207 QUrl imgTo = m_current->entry()->translation(m_current->languageTo())->imageUrl(); 0208 if (imgFrom.isEmpty()) { 0209 imgFrom = imgTo; 0210 } 0211 if (imgTo.isEmpty()) { 0212 imgTo = imgFrom; 0213 } 0214 if (Prefs::flashcardsFrontImage()) { 0215 m_frontend->setQuestionImage(imgFrom); 0216 } else { 0217 m_frontend->setQuestionImage(QUrl()); 0218 } 0219 if (Prefs::flashcardsBackImage()) { 0220 m_frontend->setSolutionImage(imgTo); 0221 } else { 0222 m_frontend->setSolutionImage(QUrl()); 0223 } 0224 m_frontend->showQuestion(); 0225 } 0226 0227 void PracticeStateMachine::gradeEntryAndContinue() 0228 { 0229 grade_t currentPreGrade = m_mode->currentPreGradeForEntry(); 0230 grade_t currentGrade = m_mode->currentGradeForEntry(); 0231 0232 if (m_frontend->resultState() == AbstractFrontend::AnswerCorrect) { 0233 m_current->updateStatisticsRightAnswer(currentPreGrade, currentGrade); 0234 } else { 0235 m_current->updateStatisticsWrongAnswer(currentPreGrade, currentGrade); 0236 } 0237 0238 if (m_current->shouldChangeGrades()) { 0239 m_mode->updateGrades(); 0240 if (m_frontend->resultState() == AbstractFrontend::AnswerCorrect) { 0241 currentEntryFinished(); 0242 } 0243 } 0244 nextEntry(); 0245 }