File indexing completed on 2024-04-14 03:49:12

0001 /*
0002     SPDX-FileCopyrightText: 2009 Frederik Gladhorn <gladhorn@kde.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "writtenbackendmode.h"
0007 
0008 #include <KLocalizedString>
0009 
0010 using namespace Practice;
0011 
0012 WrittenBackendMode::WrittenBackendMode(AbstractFrontend *frontend, QObject *parent, SessionManagerBase *sessionManager, KEduVocDocument *doc)
0013     : AbstractBackendMode(frontend, parent)
0014     , m_sessionManager(sessionManager)
0015     // FIXME: Used to be m_practiceOptions.languageTo()
0016     , m_validator(new WrittenPracticeValidator(Prefs::learningLanguage(), doc))
0017     , m_doc(doc)
0018 {
0019 }
0020 
0021 bool WrittenBackendMode::setTestEntry(TestEntry *current)
0022 {
0023     AbstractBackendMode::setTestEntry(current);
0024     m_firstAttempt = true;
0025     m_frontend->showQuestion();
0026     m_lastAnswer.clear();
0027     m_synonyms.clear();
0028     m_currentHint.clear();
0029     m_validator->setEntry(current);
0030     return true;
0031 }
0032 
0033 void WrittenBackendMode::checkAnswer()
0034 {
0035     qDebug() << "check";
0036     QString answer = m_frontend->userInput().toString();
0037 
0038     // move on, the user has not changed anything or pressed enter with no answer
0039     bool answerUnchanged = (answer == m_lastAnswer) || answer.isEmpty();
0040     m_lastAnswer = answer;
0041 
0042     m_validator->validateAnswer(answer);
0043 
0044     bool isCorrect = m_current->lastErrors() & TestEntry::Correct;
0045     bool isSynonym = m_current->lastErrors() & TestEntry::Synonym;
0046 
0047     QString feedbackString = getFeedbackString(m_current->lastErrors());
0048     m_frontend->setFeedback(feedbackString);
0049 
0050     m_firstAttempt = m_firstAttempt && isSynonym; // don't count the answer as wrong if you only enter valid synonyms
0051 
0052     // first handle synonyms as they may be correct or not
0053     if (isSynonym) {
0054         addSynonym(answer);
0055         m_frontend->setSynonym(answer);
0056         m_frontend->showSynonym();
0057 
0058         if (Prefs::countSynonymsAsCorrect()) {
0059             // any of the synonyms is automatically counted as right
0060             // otherwise do nothing to give the user another chance
0061             Q_EMIT answerRight();
0062         }
0063         return;
0064     }
0065 
0066     if (isCorrect) {
0067         Q_EMIT answerRight();
0068     } else {
0069         if (answerUnchanged) {
0070             m_frontend->setFeedback(i18n("Your answer was wrong."));
0071             Q_EMIT answerWrongShowSolution();
0072         } else {
0073             m_current->addUserAnswer(answer);
0074             Q_EMIT answerWrongRetry();
0075         }
0076     }
0077 }
0078 
0079 QString WrittenBackendMode::getFeedbackString(TestEntry::ErrorTypes error)
0080 {
0081     // The user entered a synonym
0082     if (error & TestEntry::Synonym) {
0083         if (!Prefs::countSynonymsAsCorrect()) {
0084             return i18n("Your answer was a synonym. Please enter another word with the same translation.");
0085         }
0086         const QString answer = m_validator->getCorrectedAnswer();
0087         if (m_synonyms.contains(answer)) {
0088             return i18n("Your answer was an already entered synonym.");
0089         } else {
0090             if (error & TestEntry::PunctuationMistake) {
0091                 return i18n("Your answer was a synonym and your punctuation was wrong.");
0092             } else if (error & TestEntry::CapitalizationMistake) {
0093                 return i18n("Your answer was a synonym and your capitalization was wrong.");
0094             } else if (error & TestEntry::AccentMistake) {
0095                 return i18n("Your answer was a synonym and accents were wrong.");
0096             } else {
0097                 return i18n("Your answer was a synonym.");
0098             }
0099         }
0100     }
0101 
0102     // The answer was wrong
0103     if (error & TestEntry::Wrong) {
0104         if ((error & TestEntry::PunctuationMistake) && !Prefs::ignorePunctuationMistakes()) {
0105             return i18n("Your answer was wrong as punctuation mistakes are not accepted. Please try again.");
0106         } else if ((error & TestEntry::CapitalizationMistake) && !Prefs::ignoreCapitalizationMistakes()) {
0107             return i18n("Your answer was wrong as capitalization mistakes are not accepted. Please try again.");
0108         } else if ((error & TestEntry::AccentMistake) && !Prefs::ignoreAccentMistakes()) {
0109             return i18n("Your answer was wrong as accent mistakes are not accepted. Please try again.");
0110         } else {
0111             return i18n("Your answer was wrong. Please try again.");
0112         }
0113     }
0114 
0115     // The answer was right
0116     if (m_firstAttempt) {
0117         if ((error & TestEntry::PunctuationMistake)) {
0118             return i18n("Your answer was right, but your punctuation was wrong.");
0119         } else if ((error & TestEntry::CapitalizationMistake)) {
0120             return i18n("Your answer was right, but your capitalization was wrong.");
0121         } else if ((error & TestEntry::AccentMistake)) {
0122             return i18n("Your answer was right, but accents were wrong.");
0123         } else {
0124             return i18n("Your answer was right.");
0125         }
0126     } else {
0127         if ((error & TestEntry::PunctuationMistake)) {
0128             return i18n("Your answer was right... but not on the first try and your punctuation was wrong.");
0129         } else if ((error & TestEntry::CapitalizationMistake)) {
0130             return i18n("Your answer was right... but not on the first try and your capitalization was wrong.");
0131         } else if ((error & TestEntry::AccentMistake)) {
0132             return i18n("Your answer was right... but not on the first try and accents were wrong.");
0133         } else {
0134             return i18n("Your answer was right... but not on the first try.");
0135         }
0136     }
0137 }
0138 
0139 void WrittenBackendMode::hintAction()
0140 {
0141     QString solution = m_current->entry()->translation(m_current->languageTo())->text();
0142     m_currentHint = solution.left(m_currentHint.size() + 1);
0143     if (m_currentHint.size() == solution.size()) {
0144         // show solution
0145         m_frontend->setFeedback(i18n("You revealed the answer by using too many hints."));
0146         m_frontend->setResultState(AbstractFrontend::AnswerWrong);
0147         if (m_frontend->userInput().toString() == m_current->entry()->translation(m_current->languageTo())->text()) {
0148             m_frontend->setFeedbackState(AbstractFrontend::AnswerCorrect);
0149         } else {
0150             m_frontend->setFeedbackState(AbstractFrontend::AnswerWrong);
0151         }
0152         m_frontend->showSolution();
0153     } else {
0154         m_frontend->setHint(i18n("The solution starts with: %1", m_currentHint));
0155     }
0156 
0157     m_lastAnswer = m_frontend->userInput().toString();
0158 }
0159 
0160 #include "moc_writtenbackendmode.cpp"