mirror of
https://github.com/jorenchik/mdemory.git
synced 2026-03-22 00:26:21 +00:00
layout and mdem buffer struct
This commit is contained in:
@@ -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
|
||||
);
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user