Initial commit
This commit is contained in:
@@ -0,0 +1,284 @@
|
||||
#include "testingWidget.h"
|
||||
|
||||
TestingWidget::TestingWidget(QWidget *pWidget)
|
||||
: QWidget(pWidget), m_currentComplexityName("everything"),
|
||||
m_currentTopicName("everything"), m_file("./QuestionsXML/questions.xml") {
|
||||
setupUi(dynamic_cast<QWidget *>(this));
|
||||
|
||||
connect(m_pbConfirm, &QPushButton::clicked, this,
|
||||
&TestingWidget::slotClickedConfirm);
|
||||
|
||||
connect(m_pbStart, &QPushButton::clicked, this,
|
||||
&TestingWidget::slotClickedStart);
|
||||
connect(m_pbStop, &QPushButton::clicked, this,
|
||||
&TestingWidget::slotResetTesting);
|
||||
|
||||
connect(m_rbAllDifficulties, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedComplexity);
|
||||
connect(m_rbEasy, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedComplexity);
|
||||
connect(m_rbMedium, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedComplexity);
|
||||
connect(m_rbHard, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedComplexity);
|
||||
|
||||
connect(m_rbAllTopics, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedTopics);
|
||||
connect(m_rbDiscreteMathematics, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedTopics);
|
||||
connect(m_rbHashFunction, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedTopics);
|
||||
connect(m_rbHashTable, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedTopics);
|
||||
connect(m_rbAlgorithm, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedTopics);
|
||||
|
||||
m_frmConfirm->hide();
|
||||
}
|
||||
|
||||
inline void TestingWidget::hideCheckBoxes() {
|
||||
QCheckBox *currentCheckBox;
|
||||
for (unsigned i = 0; i < 9; ++i) {
|
||||
currentCheckBox = findChild<QCheckBox *>(QString("m_cbIndex%1").arg(i));
|
||||
currentCheckBox->hide();
|
||||
}
|
||||
}
|
||||
|
||||
inline void TestingWidget::showCheckBoxes() {
|
||||
QCheckBox *currentCheckBox;
|
||||
for (unsigned i = 0, size = m_answers.size(); i < size; ++i) {
|
||||
currentCheckBox = findChild<QCheckBox *>(QString("m_cbIndex%1").arg(i));
|
||||
currentCheckBox->show();
|
||||
currentCheckBox->setText(m_answers[i].first);
|
||||
}
|
||||
}
|
||||
|
||||
inline QString TestingWidget::getHTMLQuestion(QDomElement element) {
|
||||
QString currentQuestion;
|
||||
|
||||
element = element.firstChildElement();
|
||||
do {
|
||||
switch (getTagsEnumFromQString(element.tagName())) {
|
||||
case TagXML::Caption: {
|
||||
currentQuestion.append(QString("<h3>%1</h3>").arg(element.text()));
|
||||
} break;
|
||||
case TagXML::Text: {
|
||||
currentQuestion.append(QString(R"(
|
||||
<p align="justify">
|
||||
<var>
|
||||
<font face="Times New Roman, Times, serif">
|
||||
%2
|
||||
</font>
|
||||
</var>
|
||||
</p>
|
||||
)")
|
||||
.arg(element.text()));
|
||||
} break;
|
||||
case TagXML::Answer: {
|
||||
m_answers.append(std::make_pair(
|
||||
element.text(), element.hasAttribute("type")
|
||||
? (element.attribute("type") == "correct")
|
||||
: false));
|
||||
} break;
|
||||
case TagXML::Question: {
|
||||
throw std::invalid_argument(
|
||||
"the question cannot be nested within the question");
|
||||
} break;
|
||||
case TagXML::Undefined: {
|
||||
throw std::invalid_argument("tag undefined");
|
||||
} break;
|
||||
}
|
||||
element = element.nextSiblingElement();
|
||||
} while (not element.isNull());
|
||||
|
||||
return currentQuestion;
|
||||
}
|
||||
|
||||
inline void TestingWidget::configureInput(const QString &value) {
|
||||
hideCheckBoxes();
|
||||
resetInput();
|
||||
|
||||
if (value == "choice") {
|
||||
m_swInputData->setCurrentIndex(0);
|
||||
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
std::shuffle(m_answers.begin(), m_answers.end(),
|
||||
std::default_random_engine(seed));
|
||||
showCheckBoxes();
|
||||
} else if (value == "integer") {
|
||||
m_swInputData->setCurrentIndex(1);
|
||||
|
||||
} else if (value == "floatingPoint") {
|
||||
m_swInputData->setCurrentIndex(2);
|
||||
} else {
|
||||
throw std::invalid_argument("the type of the input option is undefined");
|
||||
}
|
||||
}
|
||||
|
||||
inline bool TestingWidget::showNextQuestion() {
|
||||
bool continueFlag = true;
|
||||
|
||||
auto checkType = [](const QString &value) -> bool {
|
||||
return bool{value == "choice" || value == "integer" ||
|
||||
value == "floatingPoint"};
|
||||
};
|
||||
|
||||
while (not m_currentQuestion.isNull() && continueFlag) {
|
||||
|
||||
m_currentTypeName = m_currentQuestion.attribute("type");
|
||||
if ((m_currentTopicName == "everything" ||
|
||||
m_currentQuestion.attribute("category")
|
||||
.split('|')
|
||||
.contains(m_currentTopicName)) &&
|
||||
(m_currentComplexityName == "everything" ||
|
||||
m_currentComplexityName ==
|
||||
m_currentQuestion.attribute("complexity")) &&
|
||||
checkType(m_currentTypeName)) {
|
||||
m_answers.clear();
|
||||
m_testingTextBrowser->setHtml(getHTMLQuestion(m_currentQuestion));
|
||||
|
||||
configureInput(m_currentTypeName);
|
||||
|
||||
continueFlag = false;
|
||||
}
|
||||
m_currentQuestion = m_currentQuestion.nextSiblingElement("question");
|
||||
}
|
||||
|
||||
return (not continueFlag);
|
||||
}
|
||||
|
||||
inline void TestingWidget::setEnabledGUIStartTesting(bool flag) {
|
||||
m_gbTopics->setEnabled(flag);
|
||||
m_gbDifficulty->setEnabled(flag);
|
||||
m_pbStart->setEnabled(flag);
|
||||
m_pbStop->setDisabled(flag);
|
||||
m_frmConfirm->setVisible(not flag);
|
||||
}
|
||||
|
||||
inline TestingWidget::TagXML
|
||||
TestingWidget::getTagsEnumFromQString(const QString &value) {
|
||||
TagXML result = {value == "question" ? TagXML::Question
|
||||
: value == "caption" ? TagXML::Caption
|
||||
: value == "text" ? TagXML::Text
|
||||
: value == "answer" ? TagXML::Answer
|
||||
: TagXML::Undefined};
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Slots
|
||||
*/
|
||||
|
||||
inline void TestingWidget::slotSwitchedTopics() {
|
||||
QString result = {m_rbAllTopics->isChecked() ? QString("everything")
|
||||
: m_rbDiscreteMathematics->isChecked()
|
||||
? QString("discreteMathematics")
|
||||
: m_rbHashFunction->isChecked() ? QString("hashFunction")
|
||||
: m_rbHashTable->isChecked() ? QString("hashTable")
|
||||
: m_rbAlgorithm->isChecked() ? QString("algorithm")
|
||||
: QString()};
|
||||
if (result.isNull()) {
|
||||
throw std::invalid_argument("topic undefined");
|
||||
}
|
||||
m_currentTopicName = result;
|
||||
}
|
||||
|
||||
inline void TestingWidget::slotSwitchedComplexity() {
|
||||
QString result = {m_rbAllDifficulties->isChecked() ? QString("everything")
|
||||
: m_rbEasy->isChecked() ? QString("easy")
|
||||
: m_rbMedium->isChecked() ? QString("medium")
|
||||
: m_rbHard->isChecked() ? QString("hard")
|
||||
: QString()};
|
||||
if (result.isNull()) {
|
||||
throw std::invalid_argument("complexity undefined");
|
||||
}
|
||||
m_currentComplexityName = result;
|
||||
}
|
||||
|
||||
inline bool TestingWidget::checkAnswer(const QString &value) {
|
||||
if (m_answers.size() <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
if (value == "choice") {
|
||||
QCheckBox *currentCheckBox;
|
||||
for (unsigned i = 0, size = m_answers.size(); i < size; ++i) {
|
||||
currentCheckBox = findChild<QCheckBox *>(QString("m_cbIndex%1").arg(i));
|
||||
if (m_answers[i].second) {
|
||||
result &= currentCheckBox->isChecked();
|
||||
} else {
|
||||
result &= not currentCheckBox->isChecked();
|
||||
}
|
||||
}
|
||||
} else if (value == "integer" || value == "floatingPoint") {
|
||||
QString answer = {value == "integer" ? m_sbInteger->text()
|
||||
: m_sbDouble->text()};
|
||||
auto iter =
|
||||
std::find_if(m_answers.begin(), m_answers.end(),
|
||||
[answer](const std::pair<QString, bool> &value) -> bool {
|
||||
return (value.second == true && value.first == answer);
|
||||
});
|
||||
return (iter not_eq m_answers.end());
|
||||
} else {
|
||||
throw std::invalid_argument("input not defined");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void TestingWidget::slotClickedConfirm() {
|
||||
bool result = checkAnswer(m_currentTypeName);
|
||||
emit signalReplyGiven(result);
|
||||
|
||||
if (not showNextQuestion()) {
|
||||
setEnabledGUIStartTesting(true);
|
||||
slotResetTesting();
|
||||
}
|
||||
}
|
||||
|
||||
inline void TestingWidget::slotClickedStart() {
|
||||
bool isOpened = m_file.open(QIODevice::ReadOnly);
|
||||
emit signalFileOpened(isOpened);
|
||||
|
||||
if (isOpened) {
|
||||
bool isSet = m_document.setContent(&m_file);
|
||||
m_file.close();
|
||||
emit signalContentIsSet(isSet);
|
||||
|
||||
if (isSet) {
|
||||
QDomNode questions =
|
||||
m_document.firstChild().nextSiblingElement("questions");
|
||||
if (questions.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QDomNode firstQuestion =
|
||||
questions.firstChild().nextSiblingElement("question");
|
||||
if (firstQuestion.isNull()) {
|
||||
return;
|
||||
}
|
||||
m_currentQuestion = firstQuestion.toElement();
|
||||
if (showNextQuestion()) {
|
||||
setEnabledGUIStartTesting(false);
|
||||
emit signalStartOfTesting();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
inline void TestingWidget::resetInput() {
|
||||
QCheckBox *currentCheckBox;
|
||||
for (unsigned i = 0; i < 9; ++i) {
|
||||
currentCheckBox = findChild<QCheckBox *>(QString("m_cbIndex%1").arg(i));
|
||||
currentCheckBox->setChecked(false);
|
||||
}
|
||||
m_sbInteger->clear();
|
||||
m_sbDouble->clear();
|
||||
}
|
||||
|
||||
inline void TestingWidget::slotResetTesting() {
|
||||
m_testingTextBrowser->clear();
|
||||
setEnabledGUIStartTesting(true);
|
||||
resetInput();
|
||||
emit signalEndOfTesting();
|
||||
}
|
||||
Reference in New Issue
Block a user