mirror of
https://github.com/jorenchik/mdemory.git
synced 2026-03-22 00:26:21 +00:00
basic training functionality - all question types
This commit is contained in:
@@ -1,29 +1,9 @@
|
||||
|
||||
- What is the capital of Latvia? >
|
||||
- Rīga
|
||||
|
||||
- [cap_est] What is the capital of Estonia? >
|
||||
- Tallin
|
||||
|
||||
- What countries reside in Europe? >
|
||||
+ Latvia
|
||||
- Peru
|
||||
+ Poland
|
||||
- China
|
||||
|
||||
- Arrange these events in the order they occurred >
|
||||
-^ The Fall of the Roman Empire (476 AD)
|
||||
-^ The Renaissance (14th\-17th century)
|
||||
-^ The Industrial Revolution (18th\-19th century)
|
||||
-^ The Fall of the Roman Empire
|
||||
-^ The Renaissance
|
||||
-^ The Industrial Revolution
|
||||
|
||||
- [scient_method_order] Place the following steps of the scientific method in the correct order >
|
||||
- Ask a Question
|
||||
- Form a Hypothesis
|
||||
-^ Conduct an Experiment
|
||||
- Analyze Data
|
||||
|
||||
|
||||
- Match Planets to Their Characteristics >
|
||||
- [planet_characteristics] Match Planets to Their Characteristics >
|
||||
- Earth:
|
||||
- Contains Life
|
||||
- Mars:
|
||||
@@ -40,3 +20,26 @@
|
||||
- Neptune:
|
||||
- Farthest from the Sun
|
||||
- Has Rings
|
||||
|
||||
- What countries reside in Europe? >
|
||||
+ Latvia
|
||||
- Peru
|
||||
+ Poland
|
||||
- China
|
||||
|
||||
|
||||
|
||||
- What is the capital of Latvia? >
|
||||
- Rīga
|
||||
|
||||
- [cap_est] What is the capital of Estonia? >
|
||||
- Tallin
|
||||
|
||||
|
||||
|
||||
- [scient_method_order] Place the following steps of the scientific method in the correct order >
|
||||
- Ask a Question
|
||||
- Form a Hypothesis
|
||||
-^ Conduct an Experiment
|
||||
- Analyze Data
|
||||
|
||||
|
||||
@@ -353,7 +353,6 @@ void loadMdem() {
|
||||
questions = parseRes.value;
|
||||
makePages();
|
||||
SwitchPage(0);
|
||||
setQuestions(questions);
|
||||
std::smatch matches;
|
||||
auto filename = std::regex_search(currentPath, matches, lastPathElementExp);
|
||||
deckListLabel->setText(
|
||||
@@ -553,9 +552,11 @@ int main(int argc, char *argv[]) {
|
||||
practice,
|
||||
&QToolButton::clicked,
|
||||
[](bool checked) {
|
||||
trainWindow->show();
|
||||
trainWindow->resize(600, 300);
|
||||
});
|
||||
trainWindow->show();
|
||||
trainWindow->resize(600, 300);
|
||||
setQuestions(questions);
|
||||
}
|
||||
);
|
||||
|
||||
window.setCentralWidget(hSplitter);
|
||||
window.show();
|
||||
|
||||
@@ -2,9 +2,15 @@
|
||||
#include <QWidget>
|
||||
#include <QToolButton>
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <format>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <format>
|
||||
#include <qabstractitemview.h>
|
||||
#include <qboxlayout.h>
|
||||
#include <qcoreevent.h>
|
||||
#include <qlabel.h>
|
||||
#include <qlayoutitem.h>
|
||||
#include <qlistview.h>
|
||||
@@ -20,10 +26,18 @@
|
||||
#include <QDropEvent>
|
||||
#include <QDrag>
|
||||
#include <iostream>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QPainter>
|
||||
|
||||
#include "trainWindow.h"
|
||||
#include "parser.h"
|
||||
|
||||
enum ElementState {
|
||||
NEUTRAL = 0,
|
||||
CORRECT,
|
||||
INCORRECT
|
||||
};
|
||||
|
||||
const auto listStyle =
|
||||
"QListView {"
|
||||
" background-color: white;"
|
||||
@@ -35,15 +49,48 @@ const auto listStyle =
|
||||
"QListView::item {"
|
||||
" color: black;"
|
||||
" padding: 5px;"
|
||||
" border: 1px solid gray;"
|
||||
" background-color: white;"
|
||||
" background-color: none;"
|
||||
"}"
|
||||
"QListView::item:selected {"
|
||||
" background-color: transparent;"
|
||||
" padding-left: 0px;"
|
||||
" margin-left: 0px;"
|
||||
"}"
|
||||
"QListView::item:hover {"
|
||||
" background-color: lightyellow;"
|
||||
" padding-left: 0px;"
|
||||
" margin-left: 0px;"
|
||||
"}";
|
||||
|
||||
class CustomItemDelegate : public QStyledItemDelegate {
|
||||
public:
|
||||
CustomItemDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}
|
||||
|
||||
// Override the paint method to apply custom styling
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override {
|
||||
painter->save();
|
||||
Qt::GlobalColor color;
|
||||
auto colorIdx = index.data(Qt::UserRole + 1).toInt() ;
|
||||
switch (colorIdx) {
|
||||
case NEUTRAL:
|
||||
color = Qt::lightGray;
|
||||
break;
|
||||
case INCORRECT:
|
||||
color = Qt::red;
|
||||
break;
|
||||
case CORRECT:
|
||||
color = Qt::green;
|
||||
break;
|
||||
}
|
||||
painter->setOpacity(0.5);
|
||||
if (color) {
|
||||
painter->fillRect(option.rect, color);
|
||||
}
|
||||
painter->restore();
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
};
|
||||
|
||||
class MultiChoiceListView : public QListView
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -54,6 +101,7 @@ public:
|
||||
setAcceptDrops(true);
|
||||
setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
setSelectionMode(QAbstractItemView::NoSelection);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -65,9 +113,8 @@ public:
|
||||
explicit OrderListView(QWidget *parent = nullptr) : QListView(parent) {
|
||||
setStyleSheet(listStyle);
|
||||
setAcceptDrops(true);
|
||||
setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
setDragDropMode(QAbstractItemView::InternalMove);
|
||||
}
|
||||
|
||||
@@ -131,10 +178,21 @@ protected:
|
||||
|
||||
#include "trainWindow.moc"
|
||||
|
||||
struct GroupView {
|
||||
QWidget widget;
|
||||
QVBoxLayout vWidget;
|
||||
QLabel label;
|
||||
QScrollArea itemScroll;
|
||||
QStandardItemModel itemModel;
|
||||
MoveListView itemList;
|
||||
};
|
||||
|
||||
|
||||
// Main components
|
||||
QMainWindow *trainWindow;
|
||||
QWidget *trainWidget;
|
||||
QVBoxLayout *vTrainWidget;
|
||||
CustomItemDelegate *itemDelegate;
|
||||
|
||||
// Question
|
||||
QWidget *questionBox;
|
||||
@@ -163,19 +221,312 @@ OrderListView *orderList;
|
||||
QStandardItemModel *orderModel;
|
||||
|
||||
// Group question
|
||||
QStandardItemModel *itemModel;
|
||||
QListView *groupItemList;
|
||||
QWidget *wGroupQuestion;
|
||||
QVBoxLayout *vGroups;
|
||||
QStandardItemModel *groupItemModel;
|
||||
QListView *groupItemList;
|
||||
QWidget *wGroupQuestion;
|
||||
QVBoxLayout *vGroups;
|
||||
std::vector<QStandardItemModel*> groupModels;
|
||||
|
||||
std::default_random_engine rng;
|
||||
// Questions & State
|
||||
std::vector<Question*> trainQuestions = std::vector<Question*>();
|
||||
int32_t currentQuestionIndex = -1;
|
||||
std::vector<GroupView*> groupViews;
|
||||
|
||||
QStandardItem *makeItem(std::string content, bool isCheckable) {
|
||||
auto *item = new QStandardItem();
|
||||
item->setText(QString::fromStdString(content));
|
||||
item->setCheckable(isCheckable);
|
||||
std::default_random_engine rng;
|
||||
std::vector<QStandardItem*> itemPool;
|
||||
|
||||
/*QStandardItem *makeItem(std::string content, bool isCheckable) {*/
|
||||
/* auto *item = new QStandardItem(); */
|
||||
/* item->setText(QString::fromStdString(content));*/
|
||||
/* item->setCheckable(isCheckable);*/
|
||||
/* return item;*/
|
||||
/*};*/
|
||||
|
||||
#define ITEM_POOL_CHUNK 200
|
||||
|
||||
|
||||
QStandardItem* acquireItem() {
|
||||
if (itemPool.size() <= 0) {
|
||||
for (int i = 0; i < ITEM_POOL_CHUNK; ++i) {
|
||||
itemPool.push_back(new QStandardItem);
|
||||
}
|
||||
}
|
||||
auto item = itemPool.back();
|
||||
itemPool.pop_back();
|
||||
return item;
|
||||
};
|
||||
}
|
||||
|
||||
void releaseItem(QStandardItem** item) {
|
||||
itemPool.push_back(*item);
|
||||
(*item) = nullptr;
|
||||
}
|
||||
|
||||
void releaseAllItems() {
|
||||
std::cout <<
|
||||
std::format("Starting release, currently in the pool: {}", itemPool.size()) <<
|
||||
std::endl;
|
||||
auto releaseAllInModel = [](QStandardItemModel *model) {
|
||||
auto itemCount = model->rowCount();
|
||||
for (int i = 0; i < itemCount; ++i) {
|
||||
auto item = model->item(0);
|
||||
model->takeRow(item->row());
|
||||
releaseItem(&item);
|
||||
}
|
||||
};
|
||||
releaseAllInModel(multiChoiceModel);
|
||||
releaseAllInModel(groupItemModel);
|
||||
releaseAllInModel(orderModel);
|
||||
for (auto groupView: groupViews) {
|
||||
releaseAllInModel(&groupView->itemModel);
|
||||
}
|
||||
std::cout << std::format("All items released, currently in the pool: {}", itemPool.size()) << std::endl;
|
||||
}
|
||||
|
||||
void hideQuestionElements() {
|
||||
lQuestionText->hide();
|
||||
answerText->hide();
|
||||
orderList->hide();
|
||||
multiChoiceList->hide();
|
||||
wGroupQuestion->hide();
|
||||
}
|
||||
|
||||
void setupAnswerQuestion(MultiElementQuestion *question) {
|
||||
lQuestionText->setText(
|
||||
QString::fromStdString(question->QuestionText)
|
||||
);
|
||||
lQuestionText->show();
|
||||
auto ss = std::stringstream();
|
||||
for (auto answerEl: question->Choices) {
|
||||
ss << std::format("- {}", answerEl.Answer) << std::endl;
|
||||
}
|
||||
answerText->setText(
|
||||
QString::fromStdString(ss.str())
|
||||
);
|
||||
if (answerText->isVisible()) {
|
||||
answerText->hide();
|
||||
}
|
||||
QObject::connect(
|
||||
btnTriggerAnswer,
|
||||
&QToolButton::clicked,
|
||||
[](bool checked) {
|
||||
answerText->show();
|
||||
btnTriggerAnswer->hide();
|
||||
}
|
||||
);
|
||||
btnTriggerAnswer->show();
|
||||
}
|
||||
|
||||
void setupOrderQuestion(MultiElementQuestion *question) {
|
||||
lQuestionText->setText(
|
||||
QString::fromStdString(question->QuestionText)
|
||||
);
|
||||
lQuestionText->show();
|
||||
orderModel->clear();
|
||||
auto shuffledAnswers = question->Choices;
|
||||
std::shuffle(shuffledAnswers.begin(), shuffledAnswers.end(), rng);
|
||||
for (auto answerEl: shuffledAnswers) {
|
||||
auto *item = acquireItem();
|
||||
item->setData(NEUTRAL, Qt::UserRole + 1);
|
||||
item->setData(QVariant(), Qt::CheckStateRole);
|
||||
item->setCheckable(false);
|
||||
item->setText(QString::fromStdString(answerEl.Answer));
|
||||
orderModel->appendRow(item);
|
||||
}
|
||||
orderList->show();
|
||||
QObject::connect(
|
||||
btnTriggerAnswer,
|
||||
&QToolButton::clicked,
|
||||
[question](bool checked) {
|
||||
for (int i = 0; i < orderModel->rowCount(); ++i) {
|
||||
auto item = orderModel->item(i, 0);
|
||||
auto text = item->text();
|
||||
auto isCorrect = question->Choices[i].Answer.compare(text.toStdString()) == 0;
|
||||
if (isCorrect) {
|
||||
item->setData(CORRECT, Qt::UserRole + 1);
|
||||
} else {
|
||||
item->setData(INCORRECT, Qt::UserRole + 1);
|
||||
}
|
||||
orderList->update();
|
||||
}
|
||||
btnTriggerAnswer->hide();
|
||||
}
|
||||
);
|
||||
btnTriggerAnswer->show();
|
||||
}
|
||||
|
||||
void setupMultiChoiceQuestion(MultiElementQuestion *question) {
|
||||
lQuestionText->setText(
|
||||
QString::fromStdString(question->QuestionText)
|
||||
);
|
||||
lQuestionText->show();
|
||||
|
||||
multiChoiceModel->clear();
|
||||
for (auto answerEl: question->Choices) {
|
||||
auto *item = acquireItem();
|
||||
item->setText(QString::fromStdString(answerEl.Answer));
|
||||
item->setData(NEUTRAL, Qt::UserRole + 1);
|
||||
item->setCheckable(true);
|
||||
item->setCheckState(Qt::CheckState::Unchecked);
|
||||
multiChoiceModel->appendRow(item);
|
||||
}
|
||||
multiChoiceList->show();
|
||||
|
||||
QObject::connect(
|
||||
btnTriggerAnswer,
|
||||
&QToolButton::clicked,
|
||||
[question](bool checked) {
|
||||
for (int i = 0; i < multiChoiceModel->rowCount(); ++i) {
|
||||
auto item = multiChoiceModel->item(i, 0);
|
||||
auto isCorrect = question->Choices[i].IsCorrect == (item->checkState() == Qt::Checked);
|
||||
if (isCorrect) {
|
||||
item->setData(CORRECT, Qt::UserRole + 1);
|
||||
} else {
|
||||
item->setData(INCORRECT, Qt::UserRole + 1);
|
||||
}
|
||||
multiChoiceList->update();
|
||||
}
|
||||
btnTriggerAnswer->hide();
|
||||
}
|
||||
);
|
||||
btnTriggerAnswer->show();
|
||||
}
|
||||
|
||||
void setupGroupQuestion(GroupQuestion *question) {
|
||||
auto groupSpacer = new QSpacerItem(
|
||||
50, 50,
|
||||
QSizePolicy::Minimum,
|
||||
QSizePolicy::Expanding
|
||||
);
|
||||
|
||||
lQuestionText->setText(
|
||||
QString::fromStdString(question->QuestionText)
|
||||
);
|
||||
lQuestionText->show();
|
||||
wGroupQuestion->show();
|
||||
|
||||
for (auto group: question->Groups) {
|
||||
for (auto itemText: group.elements) {
|
||||
auto *qItem = acquireItem();
|
||||
qItem->setData(NEUTRAL, Qt::UserRole + 1);
|
||||
qItem->setCheckable(false);
|
||||
qItem->setData(QVariant(), Qt::CheckStateRole);
|
||||
qItem->setText(QString::fromStdString(itemText));
|
||||
groupItemModel->appendRow(qItem);
|
||||
}
|
||||
}
|
||||
groupItemList->update();
|
||||
|
||||
auto makeGroup = []() {
|
||||
auto groupView = new GroupView;
|
||||
vGroups->addWidget(&groupView->label);
|
||||
vGroups->addWidget(&groupView->itemList);
|
||||
groupView->itemList.setModel(&groupView->itemModel);
|
||||
groupView->itemList.setMaximumHeight(100);
|
||||
groupView->itemList.setItemDelegate(itemDelegate);
|
||||
/*groupView->itemScroll.setWidget(&groupView->itemScroll);*/
|
||||
groupView->widget.setLayout(&groupView->vWidget);
|
||||
groupView->widget.layout()->addWidget(&groupView->label);
|
||||
groupView->widget.layout()->addWidget(&groupView->itemList);
|
||||
return groupView;
|
||||
};
|
||||
|
||||
for (int k = 0; k < groupViews.size(); k++) {
|
||||
groupViews[k]->widget.hide();
|
||||
}
|
||||
for (int i = 0; i < question->Groups.size(); i++) {
|
||||
GroupView *groupView;
|
||||
if (i < groupViews.size()) {
|
||||
groupView = groupViews[i];
|
||||
} else {
|
||||
groupView = makeGroup();
|
||||
groupViews.push_back(groupView);
|
||||
}
|
||||
groupView->label.setText(
|
||||
QString::fromStdString(question->Groups[i].name)
|
||||
);
|
||||
vGroups->addWidget(&groupView->widget);
|
||||
groupView->widget.show();
|
||||
}
|
||||
vGroups->addItem(groupSpacer);
|
||||
|
||||
QObject::connect(
|
||||
btnTriggerAnswer,
|
||||
&QToolButton::clicked,
|
||||
[question](bool checked) {
|
||||
for (int i = 0; i < groupItemModel->rowCount(); ++i) {
|
||||
auto item = groupItemModel->item(i, 0);
|
||||
item->setData(INCORRECT, Qt::UserRole + 1);
|
||||
}
|
||||
for (int i = 0; i < groupViews.size(); i++) {
|
||||
auto groupView = groupViews[i];
|
||||
auto group = question->Groups[i];
|
||||
for (int j = 0; j < groupView->itemModel.rowCount(); ++j) {
|
||||
auto item = groupView->itemModel.item(j, 0);
|
||||
auto itemText = item->text().toStdString();
|
||||
bool found = false;
|
||||
for (int k = 0; k < group.elements.size(); ++k) {
|
||||
if (group.elements[k].compare(itemText) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
item->setData(CORRECT, Qt::UserRole + 1);
|
||||
} else {
|
||||
item->setData(INCORRECT, Qt::UserRole + 1);
|
||||
}
|
||||
}
|
||||
groupView->itemList.update();
|
||||
}
|
||||
btnTriggerAnswer->hide();
|
||||
}
|
||||
);
|
||||
btnTriggerAnswer->show();
|
||||
}
|
||||
|
||||
void setupQuestion(Question *question) {
|
||||
hideQuestionElements();
|
||||
releaseAllItems();
|
||||
QObject::disconnect(btnTriggerAnswer, 0, 0, 0);
|
||||
if (auto *question = dynamic_cast<MultiElementQuestion*>(trainQuestions[currentQuestionIndex])) {
|
||||
switch (question->type) {
|
||||
case MultiElementType::Order:
|
||||
setupOrderQuestion(question);
|
||||
break;
|
||||
case MultiElementType::MultiChoice:
|
||||
setupMultiChoiceQuestion(question);
|
||||
break;
|
||||
case MultiElementType::Regular:
|
||||
setupAnswerQuestion(question);
|
||||
break;
|
||||
}
|
||||
} else if (auto *question = dynamic_cast<GroupQuestion*>(trainQuestions[currentQuestionIndex])) {
|
||||
setupGroupQuestion(question);
|
||||
}
|
||||
}
|
||||
|
||||
void updatePaginationVisibility() {
|
||||
if (currentQuestionIndex == 0) {
|
||||
btnPrev->hide();
|
||||
} else {
|
||||
btnPrev->show();
|
||||
}
|
||||
if (currentQuestionIndex == trainQuestions.size() - 1) {
|
||||
btnNext->hide();
|
||||
} else {
|
||||
btnNext->show();
|
||||
}
|
||||
}
|
||||
|
||||
void setQuestions(std::vector<Question*> questions) {
|
||||
trainQuestions = questions;
|
||||
if (questions.size() <= 0) {
|
||||
return;
|
||||
}
|
||||
currentQuestionIndex = 0;
|
||||
updatePaginationVisibility();
|
||||
setupQuestion(trainQuestions[currentQuestionIndex]);
|
||||
}
|
||||
|
||||
void initTrainWindow() {
|
||||
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
@@ -191,6 +542,8 @@ void initTrainWindow() {
|
||||
vTrainWidget->setAlignment(Qt::AlignCenter);
|
||||
trainWidget->setObjectName("answer-question-widget");
|
||||
|
||||
itemDelegate = new CustomItemDelegate(multiChoiceList);
|
||||
|
||||
{ // Make the question box.
|
||||
questionBox = new QWidget();
|
||||
vQuestionBox = new QVBoxLayout();
|
||||
@@ -220,6 +573,7 @@ void initTrainWindow() {
|
||||
multiChoiceList->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
questionBox->layout()->addWidget(multiChoiceList);
|
||||
multiChoiceList->hide();
|
||||
multiChoiceList->setItemDelegate(itemDelegate);
|
||||
}
|
||||
|
||||
{ // Make answer text.
|
||||
@@ -241,6 +595,7 @@ void initTrainWindow() {
|
||||
orderList = new OrderListView();
|
||||
orderList->setModel(orderModel);
|
||||
orderList->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
orderList->setItemDelegate(itemDelegate);
|
||||
|
||||
// Connect to handle the drop event properly
|
||||
QObject::connect(
|
||||
@@ -276,9 +631,24 @@ void initTrainWindow() {
|
||||
vButtonBox->addWidget(actionButtons);
|
||||
actionButtons->setLayout(hButtons);
|
||||
btnPrev->setText("Previous");
|
||||
btnTriggerAnswer->setText("Show answer");
|
||||
btnNext->setText("Next");
|
||||
QObject::connect(btnPrev, &QToolButton::clicked, []() {
|
||||
currentQuestionIndex--;
|
||||
if (currentQuestionIndex > -1) {
|
||||
setupQuestion(trainQuestions[currentQuestionIndex]);
|
||||
}
|
||||
updatePaginationVisibility();
|
||||
});
|
||||
|
||||
btnTriggerAnswer->setText("Show answer");
|
||||
|
||||
btnNext->setText("Next");
|
||||
QObject::connect(btnNext, &QToolButton::clicked, []() {
|
||||
currentQuestionIndex++;
|
||||
if (currentQuestionIndex < trainQuestions.size()) {
|
||||
setupQuestion(trainQuestions[currentQuestionIndex]);
|
||||
}
|
||||
updatePaginationVisibility();
|
||||
});
|
||||
questionBox->setObjectName("question-box");
|
||||
actionButtons->setStyleSheet(QString(
|
||||
"QToolButton {"
|
||||
@@ -301,9 +671,10 @@ void initTrainWindow() {
|
||||
auto itemScroll = new QScrollArea();
|
||||
auto vItems = new QVBoxLayout();
|
||||
itemScroll->setLayout(vItems);
|
||||
itemModel = new QStandardItemModel();
|
||||
groupItemModel = new QStandardItemModel();
|
||||
groupItemList = new MoveListView();
|
||||
groupItemList->setModel(itemModel);
|
||||
groupItemList->setItemDelegate(itemDelegate);
|
||||
groupItemList->setModel(groupItemModel);
|
||||
vItems->addWidget(groupItemList);
|
||||
hGroupQuestion->addWidget(itemScroll);
|
||||
|
||||
@@ -316,6 +687,7 @@ void initTrainWindow() {
|
||||
wGroupContainer->setLayout(vGroups);
|
||||
hGroupQuestion->addWidget(groupScroll);
|
||||
|
||||
|
||||
wGroupQuestion->setStyleSheet("padding: 0; margin: 0;");
|
||||
wGroupQuestion->hide();
|
||||
questionBox->layout()->addWidget(wGroupQuestion);
|
||||
@@ -325,165 +697,3 @@ void initTrainWindow() {
|
||||
vTrainWidget->addWidget(actionButtons);
|
||||
}
|
||||
|
||||
std::vector<Question*> trainQuestions = std::vector<Question*>();
|
||||
int32_t currentQuestionIndex = -1;
|
||||
|
||||
void hideQuestionElements() {
|
||||
lQuestionText->hide();
|
||||
answerText->hide();
|
||||
orderList->hide();
|
||||
multiChoiceList->hide();
|
||||
wGroupQuestion->hide();
|
||||
}
|
||||
|
||||
void setupAnswerQuestion(MultiElementQuestion *question) {
|
||||
hideQuestionElements();
|
||||
|
||||
lQuestionText->setText(
|
||||
QString::fromStdString(question->QuestionText)
|
||||
);
|
||||
lQuestionText->show();
|
||||
auto ss = std::stringstream();
|
||||
for (auto answerEl: question->Choices) {
|
||||
ss << std::format("- {}", answerEl.Answer) << std::endl;
|
||||
}
|
||||
answerText->setText(
|
||||
QString::fromStdString(ss.str())
|
||||
);
|
||||
if (answerText->isVisible()) {
|
||||
answerText->hide();
|
||||
}
|
||||
auto showAnswer = [](bool checked) {
|
||||
answerText->show();
|
||||
btnTriggerAnswer->hide();
|
||||
QObject::disconnect(btnTriggerAnswer, 0, 0, 0);
|
||||
};
|
||||
QObject::connect(
|
||||
btnTriggerAnswer,
|
||||
&QToolButton::clicked,
|
||||
showAnswer
|
||||
);
|
||||
btnTriggerAnswer->show();
|
||||
}
|
||||
|
||||
void setupOrderQuestion(MultiElementQuestion *question) {
|
||||
hideQuestionElements();
|
||||
|
||||
lQuestionText->setText(
|
||||
QString::fromStdString(question->QuestionText)
|
||||
);
|
||||
lQuestionText->show();
|
||||
orderModel->clear();
|
||||
auto shuffledAnswers = question->Choices;
|
||||
std::shuffle(shuffledAnswers.begin(), shuffledAnswers.end(), rng);
|
||||
for (auto answerEl: shuffledAnswers) {
|
||||
orderModel->appendRow(makeItem(answerEl.Answer, false));
|
||||
}
|
||||
orderList->show();
|
||||
auto showAnswer = [](bool checked) {
|
||||
QObject::disconnect(btnTriggerAnswer, 0, 0, 0);
|
||||
};
|
||||
QObject::connect(
|
||||
btnTriggerAnswer,
|
||||
&QToolButton::clicked,
|
||||
showAnswer
|
||||
);
|
||||
btnTriggerAnswer->show();
|
||||
}
|
||||
|
||||
void setupMultiChoiceQuestion(MultiElementQuestion *question) {
|
||||
hideQuestionElements();
|
||||
|
||||
lQuestionText->setText(
|
||||
QString::fromStdString(question->QuestionText)
|
||||
);
|
||||
lQuestionText->show();
|
||||
|
||||
multiChoiceModel->clear();
|
||||
for (auto answerEl: question->Choices) {
|
||||
multiChoiceModel->appendRow(makeItem(answerEl.Answer, true));
|
||||
}
|
||||
multiChoiceList->show();
|
||||
|
||||
auto showAnswer = [](bool checked) {
|
||||
QObject::disconnect(btnTriggerAnswer, 0, 0, 0);
|
||||
};
|
||||
QObject::connect(
|
||||
btnTriggerAnswer,
|
||||
&QToolButton::clicked,
|
||||
showAnswer
|
||||
);
|
||||
btnTriggerAnswer->show();
|
||||
}
|
||||
|
||||
void setupGroupQuestion(GroupQuestion *question) {
|
||||
auto groupSpacer = new QSpacerItem(
|
||||
50, 50,
|
||||
QSizePolicy::Minimum,
|
||||
QSizePolicy::Expanding
|
||||
);
|
||||
|
||||
hideQuestionElements();
|
||||
|
||||
lQuestionText->setText(
|
||||
QString::fromStdString(question->QuestionText)
|
||||
);
|
||||
lQuestionText->show();
|
||||
wGroupQuestion->show();
|
||||
|
||||
for (auto group: question->Groups) {
|
||||
for (auto item: group.elements) {
|
||||
itemModel->appendRow(makeItem(item, false));
|
||||
}
|
||||
}
|
||||
auto makeAGroup = [](std::string groupName) {
|
||||
auto groupLabel = new QLabel(QString::fromStdString(groupName));
|
||||
auto scrollArea = new QScrollArea();
|
||||
auto groupModel = new QStandardItemModel();
|
||||
auto groupList = new MoveListView();
|
||||
vGroups->addWidget(groupLabel);
|
||||
vGroups->addWidget(groupList);
|
||||
groupList->setModel(groupModel);
|
||||
groupList->setMaximumHeight(100);
|
||||
};
|
||||
|
||||
for (auto group: question->Groups) {
|
||||
makeAGroup(group.name);
|
||||
}
|
||||
vGroups->addItem(groupSpacer);
|
||||
|
||||
auto showAnswer = [](bool checked) {
|
||||
QObject::disconnect(btnTriggerAnswer, 0, 0, 0);
|
||||
};
|
||||
QObject::connect(
|
||||
btnTriggerAnswer,
|
||||
&QToolButton::clicked,
|
||||
showAnswer
|
||||
);
|
||||
btnTriggerAnswer->show();
|
||||
}
|
||||
|
||||
void setQuestions(std::vector<Question*> questions) {
|
||||
trainQuestions = questions;
|
||||
if (questions.size() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// setupFirstQuestion
|
||||
currentQuestionIndex = 0;
|
||||
if (auto *question = dynamic_cast<MultiElementQuestion*>(trainQuestions[currentQuestionIndex])) {
|
||||
switch (question->type) {
|
||||
case MultiElementType::Order:
|
||||
setupOrderQuestion(question);
|
||||
break;
|
||||
case MultiElementType::MultiChoice:
|
||||
setupMultiChoiceQuestion(question);
|
||||
break;
|
||||
case MultiElementType::Regular:
|
||||
setupAnswerQuestion(question);
|
||||
break;
|
||||
}
|
||||
} else if (auto *question = dynamic_cast<GroupQuestion*>(trainQuestions[currentQuestionIndex])) {
|
||||
setupGroupQuestion(question);
|
||||
}
|
||||
}
|
||||
|
||||
19
tasks.md
19
tasks.md
@@ -1,3 +1,18 @@
|
||||
- [x] Augment the lexer for Order and match question;
|
||||
- [x] Parse the questions accordingly;
|
||||
- [x] Escape character;
|
||||
- [ ] Implement order question checking;
|
||||
- [ ] Implement multichoice question checking;
|
||||
- [ ] Implement group question checking;
|
||||
- [ ] Ensure no duplicates in questions where it matters.
|
||||
We will need this for checking the answers;
|
||||
- [ ]
|
||||
- [ ]
|
||||
- [ ]
|
||||
- [ ]
|
||||
|
||||
|
||||
|
||||
## 1-N Answer question
|
||||
|
||||
- kfoewf >
|
||||
@@ -30,8 +45,4 @@
|
||||
- fewjpfe
|
||||
- fioewf
|
||||
|
||||
- [ ] Augment the lexer for Order and match question;
|
||||
- [ ] Parse the questions accordingly;
|
||||
- [ ] Escape character;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user