mirror of
https://github.com/jorenchik/mdemory.git
synced 2026-03-22 00:26:21 +00:00
saving a question (code generation)
This commit is contained in:
@@ -2,3 +2,6 @@
|
||||
#include "parser.h"
|
||||
|
||||
Result<ParseInfo> transpile(std::string fileContent, bool isDebug);
|
||||
|
||||
std::string escapeText(std::string text);
|
||||
std::string wrapText(std::string text, size_t width);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <qwindow.h>
|
||||
#include <qwindowdefs.h>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <QApplication>
|
||||
@@ -50,6 +51,7 @@
|
||||
#define DISTANCE 2
|
||||
#define PER_PAGE 8
|
||||
#define MDEM_BACKGROUND "#F7F7F7"
|
||||
#define WRAP_WIDTH 50
|
||||
|
||||
struct Mdem {
|
||||
QWidget wMdem;
|
||||
@@ -104,6 +106,7 @@ QToolButton* nextButton;
|
||||
QLabel* paginationLabel;
|
||||
|
||||
// Mdem actions
|
||||
QToolButton *save;
|
||||
QToolButton *load;
|
||||
QToolButton *practice;
|
||||
|
||||
@@ -396,10 +399,17 @@ void releaseError(ErrorView** item) {
|
||||
std::cout << std::format("Released, current pool size: {}\n", errorPool.size());
|
||||
}
|
||||
|
||||
std::string getFilename(std::string path) {
|
||||
std::smatch matches;
|
||||
auto filenameMatched = std::regex_search(path, matches, lastPathElementExp);
|
||||
return matches[2].str();
|
||||
}
|
||||
|
||||
void reloadMdem() {
|
||||
auto file = std::ifstream(currentMdem);
|
||||
std::string content;
|
||||
|
||||
// Reset the mdem list.
|
||||
for (auto mdem: mdems) {
|
||||
mdem->wMdem.hide();
|
||||
}
|
||||
@@ -408,12 +418,11 @@ void reloadMdem() {
|
||||
}
|
||||
questions.clear();
|
||||
|
||||
std::smatch matches;
|
||||
auto filenameMatched = std::regex_search(currentMdem, matches, lastPathElementExp);
|
||||
auto filename = matches[2];
|
||||
if (filename.str().length() > 0) {
|
||||
// Get filename.
|
||||
auto filename = getFilename(currentMdem);
|
||||
if (filename.length() > 0) {
|
||||
deckListLabel->setText(
|
||||
QString::fromStdString(std::format("mdem: {}", filename.str()))
|
||||
QString::fromStdString(std::format("mdem: {}", filename))
|
||||
);
|
||||
} else {
|
||||
deckListLabel->setText("");
|
||||
@@ -453,7 +462,7 @@ void reloadMdem() {
|
||||
QString::fromStdString(
|
||||
std::format(
|
||||
"Error while transpiling {}: {} ({}:{})",
|
||||
filename.str(),
|
||||
filename,
|
||||
res.error,
|
||||
res.row,
|
||||
res.column
|
||||
@@ -481,16 +490,10 @@ void pickDirectory(QString directory) {
|
||||
std::smatch matches;
|
||||
|
||||
// Update label.
|
||||
auto filenameMatched = std::regex_search(
|
||||
currentPath,
|
||||
matches,
|
||||
lastPathElementExp
|
||||
);
|
||||
auto filename = matches[2];
|
||||
mdemLabel->setText(QString::fromStdString(
|
||||
std::format(
|
||||
"memorybase: {}",
|
||||
filename.str()
|
||||
getFilename(currentPath)
|
||||
)
|
||||
));
|
||||
|
||||
@@ -582,15 +585,78 @@ int main(int argc, char *argv[]) {
|
||||
hTop->addWidget(deckListLabel);
|
||||
hTop->addStretch(1);
|
||||
|
||||
load = new QToolButton();
|
||||
practice = new QToolButton();
|
||||
save = new QToolButton;
|
||||
load = new QToolButton;
|
||||
practice = new QToolButton;
|
||||
|
||||
hTop->addWidget(save);
|
||||
hTop->addWidget(load);
|
||||
hTop->addWidget(practice);
|
||||
|
||||
// Buttons
|
||||
save->setText("Save");
|
||||
load->setText("Load");
|
||||
practice->setText("Practice");
|
||||
QObject::connect(save, &QToolButton::clicked, []() {
|
||||
auto filename = getFilename(currentMdem);
|
||||
std::stringstream ss;
|
||||
for (auto question: questions) {
|
||||
std::string cooldownPart;
|
||||
if (question->Cooldown != 0) {
|
||||
cooldownPart = std::format("[{:.2f}]", question->Cooldown);
|
||||
}
|
||||
ss << wrapText(
|
||||
std::format("- {} {} >\n",
|
||||
cooldownPart,
|
||||
escapeText(question->QuestionText)),
|
||||
WRAP_WIDTH
|
||||
);
|
||||
if (MultiElementQuestion* mw = dynamic_cast<MultiElementQuestion*>(question)) {
|
||||
for (auto choice: mw->Choices) {
|
||||
char opener;
|
||||
if (choice.IsCorrect) {
|
||||
opener = '+';
|
||||
} else {
|
||||
opener = '-';
|
||||
}
|
||||
std::string orderModifier;
|
||||
if (mw->type == MultiElementType::Order) {
|
||||
orderModifier = "^";
|
||||
}
|
||||
ss <<
|
||||
wrapText(
|
||||
std::format(
|
||||
"\t{}{} {}\n",
|
||||
opener,
|
||||
orderModifier,
|
||||
escapeText(choice.Answer)
|
||||
)
|
||||
, WRAP_WIDTH);
|
||||
}
|
||||
} else if (GroupQuestion* gq = dynamic_cast<GroupQuestion*>(question)) {
|
||||
for (auto group: gq->Groups) {
|
||||
ss << wrapText(
|
||||
std::format(
|
||||
"\t- {}:\n",
|
||||
escapeText(group.name)
|
||||
)
|
||||
, WRAP_WIDTH);
|
||||
for (auto element: group.elements) {
|
||||
ss << wrapText(
|
||||
std::format(
|
||||
"\t\t- {}\n",
|
||||
escapeText(element)
|
||||
)
|
||||
, WRAP_WIDTH);
|
||||
}
|
||||
}
|
||||
}
|
||||
ss << std::endl;
|
||||
|
||||
std::ofstream out("generated.mdem");
|
||||
out << ss.str();
|
||||
}
|
||||
});
|
||||
QObject::connect(load, &QToolButton::clicked, &reloadMdem);
|
||||
|
||||
// Mdems
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
|
||||
@@ -8,10 +9,85 @@
|
||||
#include "time.h"
|
||||
#include "config.h"
|
||||
|
||||
#define TABWIDTH 4
|
||||
|
||||
bool debug;
|
||||
std::chrono::high_resolution_clock::time_point start;
|
||||
std::chrono::high_resolution_clock::time_point end;
|
||||
|
||||
std::string wrapText(std::string text, size_t width) {
|
||||
std::string result;
|
||||
size_t currentLineLength = 0;
|
||||
size_t wordStart = 0;
|
||||
|
||||
size_t preservedSpaceCount = 0;
|
||||
for (size_t i = 0; i < text.length(); ++i) {
|
||||
if (text[i] == '\t') {
|
||||
preservedSpaceCount += TABWIDTH;
|
||||
} else if (!std::isalnum(text[i])) {
|
||||
preservedSpaceCount++;
|
||||
} else {
|
||||
wordStart = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
result += text.substr(0, wordStart);
|
||||
currentLineLength = preservedSpaceCount;
|
||||
|
||||
for (size_t i = wordStart; i < text.length(); ++i) {
|
||||
if (text[i] == ' ' || i == text.length() - 1) {
|
||||
size_t wordEnd = (i == text.length() - 1) ? i + 1 : i; // Handle the last word
|
||||
size_t wordLength = wordEnd - wordStart;
|
||||
if (currentLineLength + wordLength > width) {
|
||||
result += '\n';
|
||||
result.append(preservedSpaceCount / TABWIDTH, '\t');
|
||||
result.append(preservedSpaceCount % TABWIDTH, ' ');
|
||||
currentLineLength = preservedSpaceCount;
|
||||
}
|
||||
result += text.substr(wordStart, wordLength) + ' ';
|
||||
currentLineLength += wordLength + 1;
|
||||
wordStart = i + 1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string escapeText(std::string text) {
|
||||
std::stringstream ss;
|
||||
for (auto c: text) {
|
||||
switch(c) {
|
||||
case '\\':
|
||||
ss << "\\\\";
|
||||
break;
|
||||
case '[':
|
||||
ss << "\\[";
|
||||
break;
|
||||
case ']':
|
||||
ss << "\\]";
|
||||
break;
|
||||
case '-':
|
||||
ss << "\\-";
|
||||
break;
|
||||
case '^':
|
||||
ss << "\\^";
|
||||
break;
|
||||
case ':':
|
||||
ss << "\\:";
|
||||
break;
|
||||
case '>':
|
||||
ss << "\\>";
|
||||
break;
|
||||
case '+':
|
||||
ss << "\\+";
|
||||
break;
|
||||
default:
|
||||
ss << c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
Result<ParseInfo> transpile(std::string fileContent, bool isDebug) {
|
||||
start = std::chrono::high_resolution_clock::now();
|
||||
end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
Reference in New Issue
Block a user