layout and mdem buffer struct

This commit is contained in:
jorenchik
2024-10-18 22:58:59 +03:00
parent d9f61f59de
commit 2f2818b44b
4 changed files with 140 additions and 81 deletions

View File

@@ -13,5 +13,9 @@ enum PracticeAlgorithm {
};
void initTrainWindow();
void setQuestions(std::vector<Question*> questions, PracticeAlgorithm algorithm);
void initiatePractice(
std::vector<Question*> questions,
PracticeAlgorithm algorithm,
time_t *trainedAt
);

View File

@@ -1,3 +1,4 @@
#include <cmath>
#include <cstdio>
#include <ctime>
#include <format>
@@ -85,6 +86,11 @@ struct Mdem {
Question *question;
};
struct MdemBuffer {
std::vector<Question*> questions = std::vector<Question*>();
time_t trainedAt = 0;
};
struct ErrorView {
QWidget box;
QVBoxLayout layout;
@@ -109,11 +115,10 @@ QTreeView *mdemList;
QLabel *deckListLabel;
QVBoxLayout *hMdemScroll;
QList<Mdem*> mdems = QList<Mdem*>();
time_t trainedAt = 0;
std::vector<Question*> questions = std::vector<Question*>();
QSpacerItem *mdemSpacer;
std::vector<ErrorView*> errorPool;
std::vector<ErrorView*> errorViews;
MdemBuffer *mdemBuffer;
// Editor
Mdem* editMdem;
@@ -224,12 +229,12 @@ std::string outputMdem(std::vector<Question*> questions, time_t time = 0) {
void makePages() {
pages.clear();
auto len = questions.size();
auto len = mdemBuffer->questions.size();
for (int i = 0; i < (len / PER_PAGE) + 1; i++) {
auto startingIndex = PER_PAGE * i ;
auto amount = PER_PAGE;
if (i == questions.size() / PER_PAGE) {
amount = questions.size() % PER_PAGE;
if (i == mdemBuffer->questions.size() / PER_PAGE) {
amount = mdemBuffer->questions.size() % PER_PAGE;
}
pages.push_back(Page{startingIndex, startingIndex + amount});
}
@@ -300,9 +305,9 @@ void SwitchPage(int pageIdx);
void deleteMdem(Mdem* mdem) {
if (mdem->question) {
Question* deleted = nullptr;
for (int i = 0; i < questions.size(); ++i) {
if (questions[i] == mdem->question) {
questions.erase(questions.begin() + i);
for (int i = 0; i < mdemBuffer->questions.size(); ++i) {
if (mdemBuffer->questions[i] == mdem->question) {
mdemBuffer->questions.erase(mdemBuffer->questions.begin() + i);
delete mdem->question;
mdem->question = nullptr;
break;
@@ -507,7 +512,10 @@ void SwitchPage(int pageIdx) {
// Handle page slice
const Page& page = pages[pageIdx];
std::vector<Question*> pageSlice(questions.begin() + page.start, questions.begin() + page.end);
std::vector<Question*> pageSlice(
mdemBuffer->questions.begin() + page.start,
mdemBuffer->questions.begin() + page.end
);
CreateMdems(pageSlice);
}
@@ -558,6 +566,23 @@ std::string getFilename(std::string path) {
return matches[2].str();
}
void updateMdemInfo(std::string filename) {
if (filename.length() > 0) {
std::stringstream ss;
ss << std::format("mdem: {}", filename);
if (mdemBuffer->trainedAt > 0) {
std::tm* tm = std::localtime(&mdemBuffer->trainedAt);
char buffer[100];
std::strftime(buffer, sizeof(buffer), "%d.%m.%Y %H:%M", tm);
ss << std::endl << "Last practiced: " << std::string(buffer);
}
deckListLabel->setText(QString::fromStdString(ss.str()));
} else {
deckListLabel->setText("");
}
}
void reloadMdem() {
auto file = std::ifstream(currentMdem);
std::string content;
@@ -566,20 +591,12 @@ void reloadMdem() {
for (auto mdem: mdems) {
mdem->wMdem.hide();
}
for (auto question: questions) {
for (auto question: mdemBuffer->questions) {
delete question;
}
questions.clear();
mdemBuffer->questions.clear();
// Get filename.
auto filename = getFilename(currentMdem);
if (filename.length() > 0) {
deckListLabel->setText(
QString::fromStdString(std::format("mdem: {}", filename))
);
} else {
deckListLabel->setText("");
}
if (file) {
std::stringstream buffer;
@@ -596,17 +613,18 @@ void reloadMdem() {
if (res.error == "") {
if (res.value.lastTrainedAt == 0) {
trainedAt = 0;
mdemBuffer->trainedAt = 0;
} else {
auto timezoneOffset = settings->value("timezone").toInt();
trainedAt = res.value.lastTrainedAt + 3600 * timezoneOffset;
mdemBuffer->trainedAt = res.value.lastTrainedAt + 3600 * timezoneOffset;
}
std::cout << std::format("Last trained at: {}", trainedAt) << std::endl;
std::cout << std::format("Last trained at: {}", mdemBuffer->trainedAt) << std::endl;
questions = res.value.questions;
mdemBuffer->questions = res.value.questions;
makePages();
SwitchPage(0);
} else {
mdemBuffer->trainedAt = 0;
std::cout << std::format("Compilation error: {}", res.error) << std::endl;
for (auto question: res.value.questions) {
@@ -634,6 +652,8 @@ void reloadMdem() {
} else {
std::cout << std::format("Could not open the file: {}", currentPath) << std::endl;
}
updateMdemInfo(filename);
}
void pickDirectory(QString directory) {
@@ -662,6 +682,7 @@ void pickDirectory(QString directory) {
void setupEditorSave(bool checked) {
auto res = transpile(editor->text().toStdString(), true);
if (res.error.length() > 0) {
mdemBuffer->trainedAt = 0;
for (auto question: res.value.questions) {
delete question;
}
@@ -681,11 +702,11 @@ void setupEditorSave(bool checked) {
} else if (res.value.questions.size() == 1) {
auto oldQuestion = editMdem->question;
editMdem->question = res.value.questions[0];
for (int i = 0; i < questions.size(); ++i) {
if (questions[i] == oldQuestion) {
questions.erase(questions.begin() + i);
delete questions[i];
questions[i] = editMdem->question;
for (int i = 0; i < mdemBuffer->questions.size(); ++i) {
if (mdemBuffer->questions[i] == oldQuestion) {
mdemBuffer->questions.erase(mdemBuffer->questions.begin() + i);
delete mdemBuffer->questions[i];
mdemBuffer->questions[i] = editMdem->question;
break;
}
}
@@ -707,8 +728,8 @@ void setupEditorSave(bool checked) {
"There are no questions in your input."
);
} else {
questions.insert(
questions.begin(),
mdemBuffer->questions.insert(
mdemBuffer->questions.begin(),
res.value.questions.begin(),
res.value.questions.end()
);
@@ -721,6 +742,7 @@ void setupEditorSave(bool checked) {
};
int main(int argc, char *argv[]) {
mdemBuffer = new MdemBuffer;
QApplication app(argc, argv);
QMainWindow window;
@@ -751,9 +773,6 @@ int main(int argc, char *argv[]) {
auto formLayout = new QFormLayout;
/*auto notificationsCheckBox = new QCheckBox("Enable notifications");*/
/*formLayout->addRow(notificationsCheckBox);*/
auto characterWrap = new QSpinBox;
characterWrap->setRange(50, 150);
formLayout->addRow("Character wrap in code gen:", characterWrap);
@@ -917,20 +936,34 @@ int main(int argc, char *argv[]) {
auto cbAlgorithm = new QComboBox;
practice = new QToolButton;
hTop->addWidget(add);
hTop->addWidget(save);
hTop->addWidget(load);
hTop->addWidget(cbAlgorithm);
hTop->addWidget(practice);
// Buttons
auto buttons = new QWidget();
auto vlButtons = new QVBoxLayout();
buttons->setLayout(vlButtons);
auto buttonsTop = new QWidget();
auto hlButtonsTop = new QHBoxLayout();
buttonsTop->setLayout(hlButtonsTop);
auto buttonsBottom = new QWidget();
auto hlButtonsBottom = new QHBoxLayout();
buttonsBottom->setLayout(hlButtonsBottom);
add->setText("Add");
save->setText("Save");
load->setText("Load");
hlButtonsTop->addWidget(add);
hlButtonsTop->addWidget(save);
hlButtonsTop->addWidget(load);
cbAlgorithm->addItem("Primary", PRIMARY);
cbAlgorithm->addItem("Random", RANDOM);
cbAlgorithm->addItem("Spaced", SPACED);
practice->setText("Practice");
hlButtonsBottom->addWidget(cbAlgorithm);
hlButtonsBottom->addWidget(practice);
vlButtons->addWidget(buttonsTop);
vlButtons->addWidget(buttonsBottom);
hlButtonsTop->setContentsMargins(0, 0, 0, 0);
hlButtonsBottom->setContentsMargins(0, 5, 0, 0);
hTop->addWidget(buttons);
QObject::connect(add, &QToolButton::clicked, []() {
editMdem = nullptr;
@@ -941,7 +974,7 @@ int main(int argc, char *argv[]) {
QObject::connect(save, &QToolButton::clicked, []() {
auto filename = getFilename(currentMdem);
std::ofstream out(currentMdem);
out << outputMdem(questions, trainedAt);
out << outputMdem(mdemBuffer->questions, mdemBuffer->trainedAt);
});
QObject::connect(
practice,
@@ -949,9 +982,10 @@ int main(int argc, char *argv[]) {
[cbAlgorithm](bool checked) {
trainWindow->show();
trainWindow->resize(600, 300);
setQuestions(
questions,
static_cast<PracticeAlgorithm>(cbAlgorithm->currentData().toInt())
initiatePractice(
mdemBuffer->questions,
static_cast<PracticeAlgorithm>(cbAlgorithm->currentData().toInt()),
&mdemBuffer->trainedAt
);
}
);

View File

@@ -187,6 +187,7 @@ struct GroupView {
MoveListView itemList;
};
#define ITEM_POOL_CHUNK 200
// Main components
QMainWindow *trainWindow;
@@ -229,15 +230,17 @@ std::vector<QStandardItemModel*> groupModels;
// Questions & State
std::vector<Question*> trainQuestions = std::vector<Question*>();
int32_t currentQuestionIndex = -1;
int32_t currentQuestionIndex = -1;
std::vector<GroupView*> groupViews;
PracticeAlgorithm practiceAlgoritm;
std::default_random_engine rng;
std::vector<QStandardItem*> itemPool;
PracticeAlgorithm practiceAlgoritm;
#define ITEM_POOL_CHUNK 200
QToolButton *btnNotRemembered;
QToolButton *btnHard;
QToolButton *btnMedium;
QToolButton *btnEasy;
QStandardItem* acquireItem() {
if (itemPool.size() <= 0) {
@@ -343,6 +346,13 @@ void setupOrderQuestion(MultiElementQuestion *question) {
orderList->update();
}
btnTriggerAnswer->hide();
if (practiceAlgoritm == SPACED) {
btnNotRemembered->show();
btnHard->show();
btnMedium->show();
btnEasy->show();
}
}
);
btnTriggerAnswer->show();
@@ -482,6 +492,10 @@ void setupQuestion(Question *question) {
releaseAllItems();
QObject::disconnect(btnTriggerAnswer, 0, 0, 0);
if (auto *question = dynamic_cast<MultiElementQuestion*>(trainQuestions[currentQuestionIndex])) {
btnNotRemembered->hide();
btnHard->hide();
btnMedium->hide();
btnEasy->hide();
switch (question->type) {
case MultiElementType::Order:
setupOrderQuestion(question);
@@ -511,7 +525,16 @@ void updatePaginationVisibility() {
}
}
void setQuestions(std::vector<Question*> questions, PracticeAlgorithm algorithm) {
void initiatePractice(
std::vector<Question*> questions,
PracticeAlgorithm algorithm,
time_t *trainedAt
) {
auto now = std::chrono::system_clock::now();
time_t unix_timestamp = std::chrono::duration_cast<std::chrono::seconds>(
now.time_since_epoch()
).count();
trainQuestions = questions;
if (questions.size() <= 0) {
return;
@@ -520,6 +543,11 @@ void setQuestions(std::vector<Question*> questions, PracticeAlgorithm algorithm)
updatePaginationVisibility();
setupQuestion(trainQuestions[currentQuestionIndex]);
practiceAlgoritm = algorithm;
btnNotRemembered->hide();
btnHard->hide();
btnMedium->hide();
btnEasy->hide();
}
void initTrainWindow() {
@@ -613,13 +641,38 @@ void initTrainWindow() {
hButtons = new QHBoxLayout();
btnPrev = new QToolButton();
leftSpacer = new QSpacerItem(50, 50, QSizePolicy::Expanding, QSizePolicy::Minimum);
btnTriggerAnswer = new QToolButton();
btnNotRemembered = new QToolButton();
btnHard = new QToolButton();
btnMedium = new QToolButton();
btnEasy = new QToolButton();
btnNotRemembered->setText("Not remembered");
btnHard->setText("Hard");
btnMedium->setText("Medium");
btnEasy->setText("Easy");
btnTriggerAnswer = new QToolButton();
rightSpacer = new QSpacerItem(50, 50, QSizePolicy::Expanding, QSizePolicy::Minimum);
btnNext = new QToolButton();
hButtons->addWidget(btnPrev);
hButtons->addItem(leftSpacer);
hButtons->addWidget(btnTriggerAnswer);
hButtons->addWidget(btnNotRemembered);
hButtons->addWidget(btnHard);
QObject::connect(btnHard, &QToolButton::clicked, []() {
const double hourCooldown = 25.0;
auto question = trainQuestions[currentQuestionIndex];
question->Cooldown = hourCooldown;
});
hButtons->addWidget(btnMedium);
hButtons->addWidget(btnEasy);
hButtons->addItem(rightSpacer);
hButtons->addWidget(btnNext);
vButtonBox->addWidget(actionButtons);

View File

@@ -1,32 +0,0 @@
[
{
"directory": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/transpiler",
"command": "/usr/bin/g++ -I/home/jorenchik/Code/mdemory/src/cpp/include -std=gnu++20 -Wall -Wextra -Wpedantic -o CMakeFiles/transpiler.dir/main.cpp.o -c /home/jorenchik/Code/mdemory/src/cpp/transpiler/main.cpp",
"file": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/main.cpp",
"output": "transpiler/CMakeFiles/transpiler.dir/main.cpp.o"
},
{
"directory": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/transpiler",
"command": "/usr/bin/g++ -I/home/jorenchik/Code/mdemory/src/cpp/include -std=gnu++20 -Wall -Wextra -Wpedantic -o CMakeFiles/transpiler.dir/lexer.cpp.o -c /home/jorenchik/Code/mdemory/src/cpp/transpiler/lexer.cpp",
"file": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/lexer.cpp",
"output": "transpiler/CMakeFiles/transpiler.dir/lexer.cpp.o"
},
{
"directory": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/transpiler",
"command": "/usr/bin/g++ -I/home/jorenchik/Code/mdemory/src/cpp/include -std=gnu++20 -Wall -Wextra -Wpedantic -o CMakeFiles/transpiler.dir/parser.cpp.o -c /home/jorenchik/Code/mdemory/src/cpp/transpiler/parser.cpp",
"file": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/parser.cpp",
"output": "transpiler/CMakeFiles/transpiler.dir/parser.cpp.o"
},
{
"directory": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/transpiler",
"command": "/usr/bin/g++ -I/home/jorenchik/Code/mdemory/src/cpp/include -std=gnu++20 -Wall -Wextra -Wpedantic -o CMakeFiles/transpiler.dir/time.cpp.o -c /home/jorenchik/Code/mdemory/src/cpp/transpiler/time.cpp",
"file": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/time.cpp",
"output": "transpiler/CMakeFiles/transpiler.dir/time.cpp.o"
},
{
"directory": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/transpiler",
"command": "/usr/bin/g++ -I/home/jorenchik/Code/mdemory/src/cpp/include -std=gnu++20 -Wall -Wextra -Wpedantic -o CMakeFiles/transpiler.dir/api.cpp.o -c /home/jorenchik/Code/mdemory/src/cpp/transpiler/api.cpp",
"file": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/api.cpp",
"output": "transpiler/CMakeFiles/transpiler.dir/api.cpp.o"
}
]