1 /*
2     SPDX-FileCopyrightText: 2009 Frederik Gladhorn <gladhorn@kde.org>
3     SPDX-License-Identifier: GPL-2.0-or-later
4 */
5 
6 #include "multiplechoicebackendmode.h"
7 
8 #include <KLocalizedString>
9 
10 #include <QRandomGenerator>
11 
12 #include "multiplechoicedata.h"
13 
14 using namespace Practice;
15 
MultipleChoiceBackendMode(AbstractFrontend * frontend,QObject * parent,Practice::SessionManagerBase * sessionManager)16 MultipleChoiceBackendMode::MultipleChoiceBackendMode(AbstractFrontend *frontend, QObject *parent, Practice::SessionManagerBase *sessionManager)
17     : AbstractBackendMode(frontend, parent)
18     , m_sessionManager(sessionManager)
19 {
20     m_numberOfChoices = Prefs::numberMultipleChoiceAnswers();
21 }
22 
setTestEntry(TestEntry * current)23 bool MultipleChoiceBackendMode::setTestEntry(TestEntry *current)
24 {
25     m_current = current;
26     m_hints.clear();
27     m_choices.clear();
28     m_question.clear();
29 
30     prepareChoices(current);
31     populateFrontEnd();
32     return true;
33 }
34 
prepareChoices(TestEntry * current)35 void MultipleChoiceBackendMode::prepareChoices(TestEntry *current)
36 {
37     Q_UNUSED(current)
38     setQuestion(m_current->entry()->translation(m_current->languageFrom())->text());
39 
40     QStringList choices = m_sessionManager->multipleChoiceAnswers(m_numberOfChoices - 1);
41     for (const QString &choice : qAsConst(choices)) {
42         int position = QRandomGenerator::global()->bounded(m_choices.count() + 1);
43         m_choices.insert(position, choice);
44     }
45     int correctAnswer = QRandomGenerator::global()->bounded(m_choices.count() + 1);
46     m_choices.insert(correctAnswer, m_current->entry()->translation(m_current->languageTo())->text());
47     setCorrectAnswer(correctAnswer);
48 }
49 
populateFrontEnd()50 void MultipleChoiceBackendMode::populateFrontEnd()
51 {
52     MultipleChoiceData data;
53     data.question = m_question;
54     data.choices = m_choices;
55 
56     m_frontend->setQuestion(QVariant::fromValue<MultipleChoiceData>(data));
57     m_frontend->setSolution(m_correctAnswer);
58     m_frontend->setQuestionSound(m_current->entry()->translation(m_current->languageFrom())->soundUrl());
59     m_frontend->setSolutionSound(m_current->entry()->translation(m_current->languageTo())->soundUrl());
60     m_frontend->setQuestionPronunciation(m_current->entry()->translation(m_current->languageFrom())->pronunciation());
61     m_frontend->setSolutionPronunciation(m_current->entry()->translation(m_current->languageTo())->pronunciation());
62     m_frontend->setResultState(AbstractFrontend::QuestionState);
63     m_frontend->showQuestion();
64 }
65 
setQuestion(const QString & question)66 void MultipleChoiceBackendMode::setQuestion(const QString &question)
67 {
68     m_question = question;
69 }
70 
numberOfChoices()71 int MultipleChoiceBackendMode::numberOfChoices()
72 {
73     return m_numberOfChoices;
74 }
75 
setChoices(const QStringList & choices)76 void MultipleChoiceBackendMode::setChoices(const QStringList &choices)
77 {
78     m_choices = choices;
79 }
80 
setCorrectAnswer(int index)81 void MultipleChoiceBackendMode::setCorrectAnswer(int index)
82 {
83     qDebug() << "correct: " << index << m_choices.at(index);
84     m_correctAnswer = index;
85 }
86 
checkAnswer()87 void MultipleChoiceBackendMode::checkAnswer()
88 {
89     if (!m_frontend->userInput().isNull() && m_frontend->userInput().toInt() == m_correctAnswer) {
90         emit answerRight();
91     } else {
92         if (!m_frontend->userInput().isNull()) {
93             m_current->addUserAnswer(m_choices.at(m_frontend->userInput().toInt()));
94         }
95         emit answerWrongShowSolution();
96     }
97 }
98 
hintAction()99 void MultipleChoiceBackendMode::hintAction()
100 {
101     if (m_choices.count() - m_hints.count() <= 2) {
102         // show solution
103         m_frontend->setFeedback(i18n("You revealed the answer by using too many hints."));
104         emit answerWrongShowSolution();
105         return;
106     }
107 
108     int hint = -1;
109     do {
110         hint = QRandomGenerator::global()->bounded(m_choices.count());
111     } while (hint == m_correctAnswer || m_hints.contains(hint));
112     m_hints.append(hint);
113     m_frontend->setHint(QVariant(hint));
114 }
115