reimplemented all the go project files

This commit is contained in:
jorenchik
2024-09-21 17:45:01 +03:00
parent 6db962288b
commit d84e7d9cd4
12 changed files with 319 additions and 57 deletions

View File

@@ -1,4 +1,4 @@
#include "result.h"
#include "parser.h"
Result<std::vector<Question*>> Transpile(std::string fileContent);
Result<std::vector<Question*>> Transpile(std::string fileContent, bool debug);

View File

@@ -6,37 +6,31 @@
#include "lexer.h"
#include "result.h"
class Question {
public:
struct Question {
virtual std::string ToString() const = 0;
virtual ~Question() = default;
};
// Choice struct for Multiple Choice Questions
struct Choice {
std::string Answer;
bool IsCorrect;
};
class SingleAnswerQuestion : public Question {
public:
struct SingleAnswerQuestion : public Question {
std::string ID;
std::string QuestionText;
std::string Answer;
std::string Section;
// Override ToString method
std::string ToString() const override;
};
class MultipleChoiceQuestion : public Question {
public:
struct MultipleChoiceQuestion : public Question {
std::string ID;
std::string QuestionText;
std::vector<Choice> Choices;
std::string Section;
// Override ToString method
std::string ToString() const override;
};

View File

@@ -16,4 +16,6 @@ add_executable(
MdemoryApp
main.cpp
)
target_link_libraries(MdemoryApp Qt5::Widgets api)
target_include_directories(MdemoryApp PRIVATE ${CMAKE_SOURCE_DIR}/include)

View File

@@ -1,3 +1,14 @@
#include <cstdio>
#include <format>
#include <fstream>
#include <iostream>
#include <qabstractbutton.h>
#include <qlabel.h>
#include <qlayoutitem.h>
#include <qobjectdefs.h>
#include <regex>
#include <string>
#include <QApplication>
#include <QMainWindow>
#include <QVBoxLayout>
@@ -16,8 +27,10 @@
#include <QRegularExpression>
#include <QStringList>
#include <QListView>
#include <qabstractitemmodel.h>
#include "api.h"
#include "parser.h"
struct Page {
int start;
@@ -33,7 +46,6 @@ public:
QToolButton *showButton;
int labelCount;
// Method to show or hide back labels
void showBacklabels() {
for (int i = 0; i < backLabels.size(); ++i) {
if (i < labelCount) {
@@ -48,7 +60,6 @@ public:
}
}
// Constructor to create an Mdem object
Mdem() {
wMdem = new QWidget();
QVBoxLayout *vMdem = new QVBoxLayout();
@@ -62,6 +73,7 @@ public:
QHBoxLayout *hFront = new QHBoxLayout();
wFront->setMinimumHeight(60);
wFront->setLayout(hFront);
wFront->setProperty("first", "true");
wMdem->setStyleSheet(QString(
"QWidget#%1 > QWidget {"
"border-right: 1px solid gray;"
@@ -117,16 +129,41 @@ public:
}
};
QLabel *deckListLabel;
QVBoxLayout *hMdemScroll;
QSpacerItem *mdemSpacer;
QList<Mdem*> mdems;
QString workingPath = "/home/jorenchik/Code/mdemory/memorybase";
void CreateMdems(QList<Page>& questions) {
if (mdemSpacer) {
hMdemScroll->removeItem(mdemSpacer);
}
QString workingPath = "/home/jorenchik/Code/mdemory/memorybase";
QList<Mdem*> mdems = QList<Mdem*>();
std::vector<Question*> questions = std::vector<Question*>();
QLabel *deckListLabel;
QVBoxLayout *hMdemScroll;
QSpacerItem *mdemSpacer;
const int PER_PAGE = 8;
int currentPage = -1;
std::vector<Page> pages;
QToolButton* prevButton;
QToolButton* firstButton;
QToolButton* lastButton;
QToolButton* nextButton;
QList<QToolButton*> paginationButtons;
QLabel* paginationLabel;
const std::regex doubleSpaceExp(
" ",
std::regex_constants::ECMAScript | std::regex_constants::icase
);
const std::regex tabExp(
"\t",
std::regex_constants::ECMAScript | std::regex_constants::icase
);
const std::regex newLineExp(
"\n",
std::regex_constants::ECMAScript | std::regex_constants::icase
);
void CreateMdems(std::vector<Question*>& questions) {
hMdemScroll->removeItem(mdemSpacer);
for (Mdem *mdem : mdems) {
if (mdem->wMdem->isVisible()) {
@@ -134,18 +171,146 @@ void CreateMdems(QList<Page>& questions) {
}
}
// TODO
if (questions.size() > mdems.size()) {
auto amount = questions.size() - mdems.size();
for (size_t i = 0; i < amount; ++i) {
auto mdem = new Mdem();
mdems.append(mdem);
hMdemScroll->addWidget(mdem->wMdem);
}
}
auto transformAnswer = [](std::string answer) -> std::string {
answer = std::regex_replace(answer, doubleSpaceExp, " ");
answer = std::regex_replace(answer, tabExp, "");
answer = std::regex_replace(answer, newLineExp, "");
return answer;
};
for (size_t i = 0; i < questions.size(); ++i) {
if (SingleAnswerQuestion* sa = dynamic_cast<SingleAnswerQuestion*>(questions[i])) {
mdems[i]->wFrontText->setText(QString::fromStdString(sa->QuestionText));
auto answer = sa->Answer;
answer = transformAnswer(answer);
answer = std::format("- {}", answer);
mdems[i]->backLabels[0]->setText(QString::fromStdString(answer));
if (mdems[i]->wBack->isVisible()) {
mdems[i]->wBack->hide();
}
mdems[i]->labelCount = 1;
} else if (MultipleChoiceQuestion* mw = dynamic_cast<MultipleChoiceQuestion*>(questions[i])) {
mdems[i]->wFrontText->setText(
QString::fromStdString(mw->QuestionText)
);
auto choices = mw->Choices;
for (size_t k = 0; k < choices.size(); ++k) {
auto answer = choices[k].Answer;
answer = transformAnswer(answer);
answer = std::format("- {}", answer);
if (k < mdems[i]->backLabels.size()) {
mdems[i]->backLabels[k]->setText(QString::fromStdString(answer));
} else {
auto label = new QLabel();
label->setText(QString::fromStdString(answer));
mdems[i]->backLabels.push_back(label);
mdems[i]->wBack->layout()->addWidget(label);
}
}
mdems[i]->labelCount = choices.size();
}
if (!mdems[i]->wMdem->isVisible()) {
mdems[i]->wMdem->show();
}
}
hMdemScroll->addItem(mdemSpacer);
}
void SwitchPage(int pageIdx, QList<Page>& pages, QList<Mdem*>& mdems) {
for (Mdem *mdem : mdems) {
const int DISTANCE = 2;
void makePages() {
pages.clear();
auto len = 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;
}
pages.push_back(Page{startingIndex, startingIndex + amount});
}
}
void SwitchPage(int pageIdx) {
currentPage = pageIdx;
// Hide all pagination buttons
for (auto& button : paginationButtons) {
button->hide();
}
int l = 0;
char buffer[50];
snprintf(buffer, sizeof(buffer), "Page: %d", pageIdx + 1);
paginationLabel->setText(buffer);
// Hide widgets in mdems
for (auto& mdem : mdems) {
if (mdem->wBack->isVisible()) {
mdem->wBack->hide();
mdem->showButton->setText("Show");
}
}
// TODO
// Update pagination buttons
for (int k = -DISTANCE; k <= DISTANCE; ++k) {
if (pageIdx + k >= 0 && pageIdx + k < pages.size()) {
auto button = paginationButtons[l];
snprintf(buffer, sizeof(buffer), "%d", pageIdx + k + 1);
button->setText(buffer);
if (pageIdx + k != pageIdx) {
button->show();
} else {
button->hide();
}
++l;
}
}
// Handle first and last buttons
if (pageIdx > 0 && pages.size() > 1) {
firstButton->show();
} else {
firstButton->hide();
}
if (pageIdx < pages.size() - 1 && pages.size() > 1) {
lastButton->show();
} else {
lastButton->hide();
}
// Handle next and previous buttons
if (!pages.empty() && currentPage < pages.size() - 1) {
nextButton->show();
} else {
nextButton->hide();
}
if (!pages.empty() && currentPage >= 1) {
prevButton->show();
} else {
prevButton->hide();
}
// Handle page slice
const Page& page = pages[pageIdx];
std::vector<Question*> pageSlice(questions.begin() + page.start, questions.begin() + page.end);
CreateMdems(pageSlice);
}
int main(int argc, char *argv[]) {
@@ -154,45 +319,74 @@ int main(int argc, char *argv[]) {
QSplitter *hSplitter = new QSplitter();
// LeftSide
QWidget *leftWidget = new QWidget();
QVBoxLayout *leftLayout = new QVBoxLayout();
QLabel *mdemLabel = new QLabel("Mdems");
QFileSystemModel *model = new QFileSystemModel();
QTreeView *mdemList = new QTreeView();
QWidget *leftWidget = new QWidget();
QVBoxLayout *leftLayout = new QVBoxLayout();
QLabel *mdemLabel = new QLabel("Mdems");
QFileSystemModel *model = new QFileSystemModel();
QTreeView *mdemList = new QTreeView();
mdemSpacer = new QSpacerItem(50, 50, QSizePolicy::Minimum, QSizePolicy::Expanding);
leftWidget->setLayout(leftLayout);
leftLayout->addWidget(mdemLabel);
model->setRootPath(workingPath);
mdemList->setModel(model);
QObject::connect(
mdemList,
&QTreeView::doubleClicked,
[model](const QModelIndex &index) {
auto fileInfo = model->fileInfo(index);
auto path = fileInfo.filePath().toStdString();
auto file = std::ifstream(path);
std::string content;
if (file) {
std::stringstream buffer;
buffer << file.rdbuf();
content = buffer.str();
auto parseRes = Transpile(content, true);
for (auto question: questions) {
delete question;
}
questions.clear();
questions = parseRes.value;
makePages();
SwitchPage(0);
} else {
std::cout << std::format("Could not open the file: {}", path) << std::endl;
}
}
);
QModelIndex rootIndex = model->index("/home/jorenchik/Code/mdemory/memorybase");
QModelIndex rootIndex = model->index(
"/home/jorenchik/Code/mdemory/memorybase"
);
mdemList->setRootIndex(rootIndex);
leftLayout->addWidget(mdemList);
// DeckList
QLabel *deckLabel = new QLabel("Decks");
QListView *deckList = new QListView();
QLabel *deckLabel = new QLabel("Decks");
QListView *deckList = new QListView();
leftLayout->addWidget(deckLabel);
leftLayout->addWidget(deckList);
// RightSide
QWidget *rightWidget = new QWidget();
QWidget *rightWidget = new QWidget();
QVBoxLayout *rightLayout = new QVBoxLayout();
rightWidget->setLayout(rightLayout);
QWidget *top = new QWidget();
QWidget *top = new QWidget();
QHBoxLayout *hTop = new QHBoxLayout();
deckListLabel = new QLabel("Mdem: todo.mdem");
deckListLabel = new QLabel("Mdem: todo.mdem");
top->setLayout(hTop);
rightLayout->addWidget(top);
hTop->addWidget(deckListLabel);
hTop->addStretch(1);
QToolButton *refresh = new QToolButton();
QToolButton *refresh = new QToolButton();
QToolButton *practice = new QToolButton();
QToolButton *shuffle = new QToolButton();
QToolButton *shuffle = new QToolButton();
hTop->addWidget(refresh);
hTop->addWidget(shuffle);
@@ -204,13 +398,14 @@ int main(int argc, char *argv[]) {
practice->setText("Practice");
// Mdems
QScrollArea *mdemScroll = new QScrollArea();
QWidget *mdemContainer = new QWidget();
QScrollArea *mdemScroll = new QScrollArea();
QWidget *mdemContainer = new QWidget();
hMdemScroll = new QVBoxLayout();
mdemScroll->setWidget(mdemContainer);
mdemScroll->setWidgetResizable(true);
mdemContainer->setLayout(hMdemScroll);
rightLayout->addWidget(mdemScroll);
hMdemScroll->addItem(mdemSpacer);
// Pagination
hSplitter->addWidget(leftWidget);
@@ -218,6 +413,70 @@ int main(int argc, char *argv[]) {
hSplitter->setStretchFactor(0, 1);
hSplitter->setStretchFactor(1, 3);
auto pagination = new QWidget();
auto hPagination = new QHBoxLayout();
pagination->setLayout(hPagination);
firstButton = new QToolButton();
firstButton->setText(QString::fromStdString("<<"));
hPagination->addWidget(firstButton);
firstButton->hide();
QObject::connect(firstButton, &QToolButton::clicked, [](bool checked) {
if (pages.size() > 0) {
SwitchPage(0);
}
});
prevButton = new QToolButton();
prevButton->setText(QString::fromStdString("<"));
hPagination->addWidget(prevButton);
prevButton->hide();
QObject::connect(prevButton, &QToolButton::clicked, [](bool checked) {
if (pages.size() > 0) {
SwitchPage(currentPage - 1);
}
});
for (int i = 0; i < PER_PAGE; i++) {
auto elButton = new QToolButton();
elButton->setText(QString("%1").arg(i+1));
hPagination->addWidget(elButton);
elButton->hide();
QObject::connect(elButton, &QToolButton::clicked, [elButton](bool checked) {
auto pageNum = std::stoi(elButton->text().toStdString().c_str());
auto pageIdx = pageNum - 1;
if (pageIdx < pages.size()) {
SwitchPage(pageIdx);
}
});
paginationButtons.push_back(elButton);
}
nextButton = new QToolButton();
nextButton->setText(QString::fromStdString(">"));
hPagination->addWidget(nextButton);
nextButton->hide();
QObject::connect(nextButton, &QToolButton::clicked, [](bool checked) {
if (pages.size() > 0) {
SwitchPage(currentPage + 1);
}
});
lastButton = new QToolButton();
lastButton->setText(QString::fromStdString(">>"));
hPagination->addWidget(lastButton);
lastButton->hide();
QObject::connect(lastButton, &QToolButton::clicked, [](bool checked) {
if (pages.size() > 0) {
SwitchPage(pages.size() - 1);
}
});
hPagination->addStretch(1);
paginationLabel = new QLabel();
hPagination->addWidget(paginationLabel);
rightLayout->addWidget(pagination);
window.setCentralWidget(hSplitter);
window.show();
return app.exec();

View File

@@ -1,22 +1,21 @@
# Set sources
set(SOURCES
set(
SOURCES
main.cpp
)
add_library(
api
lexer.cpp
parser.cpp
time.cpp
api.cpp
)
#include_directories(${CMAKE_SOURCE_DIR}/include)
add_library(api api.cpp)
# Add the executable (CLI)
add_executable(transpiler ${SOURCES})
target_compile_options(transpiler PRIVATE -Wall -Wextra -Wpedantic)
target_link_libraries(transpiler api)
#add_library(api api.cpp)
#target_link_libraries(transpiler PRIVATE api)
target_compile_options(transpiler PRIVATE -Wall -Wextra -Wpedantic)
target_include_directories(transpiler PRIVATE ${CMAKE_SOURCE_DIR}/include)
target_include_directories(api PUBLIC ${CMAKE_SOURCE_DIR}/include)

View File

@@ -6,9 +6,17 @@
#include "lexer.h"
#include "parser.h"
#include "time.h"
#include "config.h"
Result<std::vector<Question*>> Transpile(std::string fileContent) {
bool debug;
std::chrono::high_resolution_clock::time_point start;
std::chrono::high_resolution_clock::time_point end;
Result<std::vector<Question*>> Transpile(std::string fileContent, bool isDebug) {
start = std::chrono::high_resolution_clock::now();
end = std::chrono::high_resolution_clock::now();
debug = isDebug;
auto lexRes = TokenizeMdem(fileContent);
auto tokens = lexRes.value;
if (lexRes.error.length() > 0) {

View File

@@ -5,7 +5,6 @@
#include <chrono>
#include "time.h"
#include "config.h"
#include "api.h"
std::string readFile(const std::string& filePath) {
@@ -24,14 +23,11 @@ std::string readFile(const std::string& filePath) {
return content;
}
bool debug = false;
std::chrono::high_resolution_clock::time_point start;
std::chrono::high_resolution_clock::time_point end;
int main(int argc, char* argv[]) {
std::string filePath;
bool debug = false;
if (argc == 3) {
auto option = std::string(argv[1]);
if (option == "--debug") {
@@ -49,12 +45,11 @@ int main(int argc, char* argv[]) {
}
try {
start = std::chrono::high_resolution_clock::now();
std::string fileContent = readFile(filePath);
end = std::chrono::high_resolution_clock::now();
ShowTime("I/O time");
auto res = Transpile(fileContent);
auto res = Transpile(fileContent, debug);
auto questions = res.value;
if (res.error.length() > 0) {
std::cout << std::format(

View File

@@ -139,6 +139,10 @@ Result<NoneType> ValidateGrammar(const std::vector<Token>& tokens) {
Result<std::vector<Question*>> ParseQuestions(const std::vector<Token>& tokens) {
auto questions = std::vector<Question*>();
if (tokens.size() == 0) {
return {questions, ""};
}
auto result = ValidateGrammar(tokens);
if (result.error.length() > 0) {
return {
@@ -152,6 +156,7 @@ Result<std::vector<Question*>> ParseQuestions(const std::vector<Token>& tokens)
std::string section;
size_t i = 0;
debug = true;
if (debug) {
std::cout << "SECTION: Parser output:\n";
}