docs, added help window, CMakeLists in root dir, other small changes

This commit is contained in:
jorenchik
2024-11-02 18:39:58 +02:00
parent 39839f95e6
commit 8e6b3f7f96
18 changed files with 124023 additions and 78606 deletions

View File

@@ -9,5 +9,5 @@ set(
"${CMAKE_CXX_FLAGS_DEBUG} -g3 -O0 -ggdb -fvar-tracking-assignments -fno-inline"
)
add_subdirectory(transpiler)
add_subdirectory(qtapp)
add_subdirectory(src/transpiler)
add_subdirectory(src/qtapp)

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 341 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 784 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 787 KiB

BIN
docs/img/screens/help.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@@ -50,6 +50,11 @@
īpašībām, piemēram, saturu, izcelsmi un struktūru;
*CSV* -- formāts, kas satur vērtības, kas ir atdalīti ar komatiem;
*Parsēšana* -- TODO;
*Buferis* -- TODO;
],
)
@@ -67,17 +72,6 @@
== Darbības sfēra
// 1) identificēt programmatūras produkta nosaukumu, piemēram, "Pārskatu ģenerators", utt.,
// 2) paskaidrot kas programmatūras produktam jādara un, ja nepieciešams, kas
// nav jādara;
// 3) aprakstīt programmatūras produkta pielietojumu.
// a) Aprakstīt, cik iespējams precīzi, iespējas, centienus un mērķi. Piemēram,
// teikums: iespēja efektīvi izstrādāt pārskatus nav tik labs, kā parametrizēti,
// lietotāja vadīti un definēti pārskati divu stundu laikā, ar iespēju ievadīt
// lietotāja parametrus dialoga režīmā.
// b) Nepieļaut pretrunas, lietojot terminus, kas līdzīgi terminiem augstāka
// līmeņa LVS 68:1996 lpp. 15. (22) specifikācijā (piemēram, Sistēmprasību
#indent-par([
// Kas ir atmiņas kartes
Atmiņas kartītes (angl. flashcards) ir izplatīts veids, kā skolēni,
@@ -218,14 +212,34 @@ slēptā formātā, kas apgrūtina kartīšu pārvaldību un pārnešanu.
== Risinājuma lietotāji
// TODO Spelling
#indent-par([
Risinājumam ir viena lietotāju grupa, kam ir pieejamas visas risinājuma
iespējas un funkcijas.
])
Risinājuma augsta līmeņa datu plūsmas ir attēlota 0. līmeņa datu plūsmas
diagrammā (DPD; skat. @fig:dpd0 attēls). Lietotāju galvenā datu apmaiņa ir
atmiņas kartīšu dati un dati par saskarni ar kartītēm.
atmiņas kartīšu dati un dati par saskarni ar kartītēm. DPD ir iekļautas trīs
datu glabātuves: failu glabātuve, pagaidu kartīšu glabātuve un konfigurācijas
glabātuve.
])
Failu glabātuve ir vieta, kur tiek glabātas kartītes vienkārša teskta formātā.
Tas ir direktorijs ar noteikta formāta failiem (skat. attēlu @fig:conceptual-er
un tabulas 2.1-2.6). Šo glabātuvi pārvalda lietotājs -- brīvi pievieno,
modificē un pārstrukturē direktorijā esošos failus un apakšdirektorijus.
Pagaidu kartīšu glabātuve glabā apskatāmās kartītes un visus izmainītos atmiņas
failiem atbilstošus kartīšu sarakstus. Glabātuve ir spēkā risinājuma programmas
darba laikā. Sākot darbu ar risinājumu, kartītes tiek ielādētas no failu
glabātuves pagaidu glabātuvē. Darbu beidzot vai pēc lietotāja izvēles, kartītes
tiek saglabātas failos, no kuriem katītes tika ielādētas. Izmaiņas pagaidu
glabātuves datos notiek ar risinājuma saskarni.
Konfigurācijas glabātuve ir fails(/-i), kuros tiek glabātas konfigurācijas
vērtības, ko uzstāda un saglabā lietotājs. Konfigurācijas glabātuvi pārvalda
lietotājs -- ir iespējams mainīt konfigurācijas faila saturu ar nosacījumu, ka
faila formāts paliek korekts un ievadītās vertības ir korektas un ir pieejamā
vērtību diapazonā.
#figure(
caption: "0.līmeņa datu plūsmas diagramma",
@@ -260,6 +274,42 @@ atmiņas kartīšu dati un dati par saskarni ar kartītēm.
#pagebreak(weak: true)
= Programmatūras prasību specifikācija
// Šajā sadaļā tiks aprakstīts TODO??
== Konceptuālais entitāšu-relāciju modelis
// TODO spelling
Risinājuma glabātie dati iekļauj atmiņas kartīšu un konfigurācijas datus, kas
tiek glabāti vienkāršos failos. Risinājums neizmantos datubāzi datu glabāšanai.
Risinājumā entitātes ir attēlotas konceptuālā entitāšu-relāciju modelī (skat. attēlu
@fig:conceptual-er).
Atmiņas kartītes tiek organizētas noteikta paplašinājuma failos, kas satur
kartītes noteiktā formātā. Kartītes ir dažādu veidu jautājumi, kas ietver
sākuma -- jautājuma tekstu un vairākus saistītus jautājuma atbildes elementus.
Ir atbildes jautājumi, kas satur vairākus vienlīdzīgus elementus, un ir grupas
jautājumi, kas satur vairākas grupas ar vairākiem tai piederošiem elementiem.
Atbildes elementiem piemīt veids, katrs atšķiras ar to, kā elements sākas, ko
nosaka sākuma simboli. Grupas elementi sastāv no teksta un pieder kādai grupai,
kam ir nosaukums.
Modelī ir iekļauti metadati, kā pēdējās mācīšanās laiks, jautājuma pārtraukuma
laiks un faila nosaukums. Pēdējās mācīšanās laiks tiek izmantots intervālu
metodē, lai reģistrētu laiku un pielietot intervālu metodi turpmākās mācību
reizēs. Jautājuma pārtraukuma laiks nosaka, cik ilgam laikam jāpaiet, lai
jautājums atkal būtu iekļauts intervālu metodes mācīšanās.
Faila nosaukums tiek izmantots kā kartīšu saraksta nosaukums -- to var izmanot,
lai nosauktu failā esošās kartītes, piemēram, to tēmu vai nolūku.
Papildus datetime TODO
#figure(
caption: "Konceptuālais entitāšu-relāciju modelis",
placement: auto,
image("img/conceptualER.svg"),
) <conceptual-er>
== Funkcionālās prasības
#let ref_df01 = [(skat. tabulu 2.1)]
@@ -1165,8 +1215,6 @@ Pirmkodam jābūt izstrādātam ar sekojošiem nosacījumiem:
+ Risinājuma pirmkods ir realizēts galvenokārt procedurālā stilā;
+ Transpilatora funkcionalitātes testu pārklājums ir 90%;
// + Saskarnes funkcionalitāte ir notestēta svarīgākās vietās (svarīgākās vietas
// ir subjektīvs jēdziens, tāpēc to definēsim kā 20%).
==== Pārnesamība
@@ -1190,10 +1238,22 @@ Uz drošību risinājumam ir sekojošas prasības:
== Daļējs funkciju projektējums
#figure(
caption: "Leksiskās analīzes aktivitāšu diagramma",
caption: "Leksiskās analīzes aktivitātes diagramma",
placement: none,
image("img/lexer_activity.svg"),
) <mdem-list-view>
) <lexing-activity>
#figure(
caption: "Parsēšanas aktivitātes diagramma",
placement: none,
image("img/parsing_activity.svg"),
) <parsing-acticity>
#figure(
caption: "Atbildes parsēšanas aktivitātes diagramma",
placement: none,
image("img/parsing_answer_activity.svg"),
) <parsing-answer-activity>
== Saskarnes projektējums
@@ -1233,6 +1293,29 @@ Uz drošību risinājumam ir sekojošas prasības:
image("img/screens/config.png"),
) <config-view>
#figure(
caption: "Apmācības skats",
placement: none,
image("img/screens/help.png"),
) <help-view>
#pagebreak(weak: true)
= Testēšanas dokumentācija
#pagebreak(weak: true)
= Projekta organizācija
#pagebreak(weak: true)
= Kvalitātes nodrošināšana
#pagebreak(weak: true)
= Konfigurācijas pārvaldība
#pagebreak(weak: true)
= Darbietiplības novērtējums
#pagebreak(weak: true)
= Secinājumi
#pagebreak(weak: true)
#heading(numbering: none, "Izmantotā literatūra un avoti")
@@ -1284,3 +1367,664 @@ Uz drošību risinājumam ir sekojošas prasības:
day: 21,
),
)<quizlet>
+ TODO UML 2.5. spec
#pagebreak(weak: true)
#heading(numbering: none, "Pielikumi")
// TODO caption
```cpp
std::vector<Token> tokens;
std::vector<char> buffer;
int32_t row;
int32_t column;
int32_t previousRow;
int32_t previousColumn;
bool textStarted = false;
bool identifierStarted = false;
bool sof;
/*
* TODO
*/
void trimString(std::string &str, std::string trimChars) {
// Noņem kreisās puses simbolus.
int padSize = 0;
bool pad = false;
for (size_t i = 0; i < str.size(); ++i) {
for (size_t k = 0; k < trimChars.size(); ++k) {
if (str[i] == trimChars[k]) {
padSize++;
pad = true;
break;
}
}
if (!pad) {
break;
}
pad = false;
}
if (padSize > 0) {
str.erase(0, padSize);
}
// Noņem labās puses simbolus.
padSize = 0;
pad = false;
for (size_t i = str.size(); i-- > 0;) {
for (size_t k = 0; k < trimChars.size(); ++k) {
if (str[i] == trimChars[k]) {
padSize++;
pad = true;
break;
}
}
if (!pad) {
break;
}
pad = false;
}
if (padSize > 0) {
str.erase(str.end() - padSize, str.end());
}
}
/*
* Izveido tekstvienību, iegūstot to no bufera beigām.
* Ja buferī ir teksta vienība pirms tekstvienības, pievieno to pirms beigu
* tekstvienības.
*/
void tokenWithBuffer(
TokenType ttype,
size_t tokenLen,
TokenType textType
) {
std::string token(buffer.end() - tokenLen, buffer.end());
if (buffer.size() > tokenLen) {
std::string prevFragment(buffer.begin(), buffer.end() - tokenLen);
trimString(prevFragment, " \n\t");
if (prevFragment.length() > 0) {
tokens.push_back(Token{
textType,
prevFragment,
previousRow,
previousColumn
});
}
}
buffer.clear();
tokens.push_back(Token{
ttype,
token,
row,
column
});
previousRow = row;
previousColumn = column;
buffer.clear();
}
/*
* Pārveido simbolu virkni tekstvienību sarakstā.
* */
Result<std::vector<Token>> tokenizeMdem(const std::string& content) {
row = 1;
column = 1;
previousRow = 1;
previousColumn = 1;
textStarted = false;
tokens.clear();
buffer.clear();
// Beidz, ja satur tikai tukšumus vai neko.
if (content.find_first_not_of(" \n\t") == std::string::npos) {
return {tokens, ""};
}
for (size_t i = 0; i < content.size(); ++i) {
char c = content[i];
// Apstrādā īpašos simbolus un tekstu.
if (c == '\n') {
row += 1;
column = 0;
}
if (c == '\\') {
i += 1;
if (i < content.size()) {
buffer.push_back(content[i]);
}
continue;
} else {
buffer.push_back(c);
}
if (!textStarted) {
if (c == '\n') {
previousRow += 1;
previousColumn = 1;
} else if (c == ' ') {
previousColumn += 1;
} else if (c == '\t') {
previousColumn += 4;
} else {
textStarted = true;
}
}
// Emitē tekstvienības.
switch (c) {
case '[': {
tokenWithBuffer(
TokenType::CooldownStart,
1,
TokenType::TextFragment
);
previousRow = row;
previousColumn = column;
textStarted = false;
identifierStarted = true;
} break;
case ']': {
if (!identifierStarted) {
return {
tokens,
"Cannot end identifier if it is not started",
tokens[i].row,
tokens[i].column
};
}
tokenWithBuffer(
TokenType::CooldownEnd,
1,
TokenType::Cooldown
);
previousRow = row;
previousColumn = column;
textStarted = false;
identifierStarted = false;
} break;
case '-': {
tokenWithBuffer(
TokenType::ElementDashStart,
1,
TokenType::TextFragment
);
previousRow = row;
previousColumn = column;
textStarted = false;
} break;
case '^': {
tokenWithBuffer(
TokenType::ElementOrderModifier,
1,
TokenType::TextFragment
);
previousRow = row;
previousColumn = column;
textStarted = false;
} break;
case ':': {
tokenWithBuffer(
TokenType::MatchGroupEnd,
1,
TokenType::TextFragment
);
previousRow = row;
previousColumn = column;
textStarted = false;
} break;
case '>': {
tokenWithBuffer(
TokenType::QuestionEnd,
1,
TokenType::TextFragment
);
previousRow = row;
previousColumn = column;
textStarted = false;
} break;
case '+': {
tokenWithBuffer(
TokenType::ElementPlusStart,
1,
TokenType::TextFragment
);
previousRow = row;
previousColumn = column;
textStarted = false;
} break;
}
column += 1;
}
// Pievieno beigu simbolu, lai atvieglotu parsēšanu.
tokenWithBuffer(
TokenType::EndOfFile,
0,
TokenType::TextFragment
);
if (debug) {
std::cout << "SECTION: Lexer output:\n";
std::cout << std::format("Token count: {}", tokens.size()) << std::endl;
for (const Token& token : tokens) {
std::cout << token.toString();
}
std::cout << "SECTION END: Lexer output\n";
}
return {tokens, ""};
}
std::string Token::toString(const TokenType* ttype) {
switch (*ttype) {
case TokenType::TextFragment: return "text fragment";
case TokenType::QuestionEnd: return "question end symbol";
case TokenType::MatchGroupEnd: return "match group end";
case TokenType::ElementDashStart: return "dash element start";
case TokenType::ElementOrderModifier: return "order element modifier";
case TokenType::ElementPlusStart: return "plus element start";
case TokenType::Cooldown: return "cooldown";
case TokenType::CooldownStart: return "start of cooldown";
case TokenType::CooldownEnd: return "end of cooldown";
case TokenType::StartOfFile: return "start of the file";
case TokenType::EndOfFile: return "end of file";
default: return "unrecognized token";
}
}
```
// TODO caption
```cpp
typedef std::map<TokenType, std::vector<TokenType>> TokenAutomata;
TokenAutomata *automata = nullptr;
/*
* Tekstvienību secības pārejas, kas nosaka, kādā secībā tekstvienības var būt.
* */
void initParserAutomata() {
automata = new TokenAutomata;
(*automata)[TokenType::TextFragment] = {
TokenType::QuestionEnd,
TokenType::ElementDashStart,
TokenType::ElementPlusStart,
TokenType::MatchGroupEnd,
TokenType::EndOfFile,
};
(*automata)[TokenType::MatchGroupEnd] = {
TokenType::ElementDashStart
};
(*automata)[TokenType::QuestionEnd] = {
TokenType::ElementDashStart,
TokenType::ElementPlusStart
};
(*automata)[TokenType::ElementDashStart] = {
TokenType::CooldownStart,
TokenType::TextFragment,
TokenType::ElementOrderModifier
};
(*automata)[TokenType::ElementOrderModifier] = {
TokenType::TextFragment
};
(*automata)[TokenType::ElementPlusStart] = {
TokenType::TextFragment
};
(*automata)[TokenType::Cooldown] = {
TokenType::CooldownEnd,
};
(*automata)[TokenType::CooldownStart] = {
TokenType::Cooldown
};
(*automata)[TokenType::CooldownEnd] = {
TokenType::TextFragment
};
(*automata)[TokenType::StartOfFile] = {
TokenType::TextFragment,
TokenType::ElementDashStart,
TokenType::EndOfFile
};
(*automata)[TokenType::EndOfFile] = {};
}
/*
* Pārbauda, vai vai tekstvienību sarakstu akceptē atbilst atbilst valodas
* automāts.
* */
Result<NoneType> ValidateGrammar(const std::vector<Token>& tokens) {
if (!automata) {
initParserAutomata();
}
for (size_t i = 0; i < tokens.size() - 1; ++i) {
Token token = tokens[i];
Token nextToken = tokens[i + 1];
if (
std::find(
(*automata)[token.tokenType].begin(),
(*automata)[token.tokenType].end(),
nextToken.tokenType
) == (*automata)[token.tokenType].end()) {
auto capitalize = [](const std::string& str) {
if (str.empty()) return str;
std::string result = str;
result[0] = std::towupper(result[0]);
return result;
};
return {
.error=std::format(
"Invalid token sequence: {} cannot precede {}",
std::string(capitalize(Token::toString(&token.tokenType))),
std::string(capitalize(Token::toString(&nextToken.tokenType)))
),
.row=token.row,
.column=token.column
};
}
}
return {};
}
// @Fix: Prevent duplicate group names and questions in ordered question (to
// simplify checking in practice).
Result<ParseInfo> parseQuestions(const std::vector<Token>& tokens) {
auto questions = std::vector<Question*>();
time_t time = 0;
auto makeResult = [&questions, &time](std::string error, Token token) -> Result<ParseInfo> {
return {
{ questions, time },
error,
token.row,
token.column
};
};
if (tokens.size() == 0) {
return makeResult("", Token());
}
auto result = ValidateGrammar(tokens);
if (result.error.length() > 0) {
return makeResult(
result.error,
Token{.row=result.row, .column=result.column}
);
}
std::string section;
size_t i = 0;
if (debug) {
std::cout << "SECTION: Parser output:\n";
}
auto isInBounds = [tokens](size_t i) {
return i < tokens.size() && tokens[i].tokenType != TokenType::EndOfFile;
};
if (isInBounds(i) && tokens[i].tokenType == TokenType::TextFragment) {
try {
auto parseToUTCTime = [](const std::string datetime, std::string format) {
std::tm tm = {};
std::istringstream ss(datetime);
ss >> std::get_time(&tm, format.c_str());
if (ss.fail()) {
throw std::runtime_error("Failed to parse datetime string");
}
std::time_t time = timegm(&tm);
return time;
};
time = parseToUTCTime(tokens[i].content.c_str(), "%d.%m.%Y %H:%M");
} catch (std::exception e) {
return makeResult(
std::format("cannot parse the time - {}", e.what()),
tokens[i]
);
}
i++;
}
while (i < tokens.size()) {
if (tokens[i].tokenType == TokenType::ElementDashStart) {
std::string questionText;
std::vector<QuestionElement> questionElements;
double cooldown;
bool isOrderQuestion = false;
bool isGroupQuestion = false;
bool isPlusQuestion = false;
// Start element parsing & add to the offset.
if (isInBounds(i + 1) && tokens[i + 1].tokenType == TokenType::ElementOrderModifier) {
return makeResult(
"cannot have order modifier ('^') in the question definition",
tokens[i + 1]
);
}
if (isInBounds(i + 1) && tokens[i + 1].tokenType == TokenType::CooldownStart) {
try {
cooldown = std::stod(tokens[i + 2].content);
} catch (std::exception e) {
return makeResult(
"error parsing cooldown",
tokens[i + 1]
);
}
questionText = tokens[i + 4].content;
i += 6;
} else {
cooldown = 0;
questionText = tokens[i + 1].content;
i += 3;
}
// Parse elements of a question.
while (isInBounds(i)) {
// Check question end.
if (isInBounds(i + 3) && tokens[i].tokenType == TokenType::ElementDashStart) {
// Distance to the possible question end.
size_t offset;
if (tokens[i + 1].tokenType == TokenType::ElementOrderModifier) {
offset = tokens[i + 2].tokenType == TokenType::CooldownStart ? 6 : 3;
} else {
offset = tokens[i + 1].tokenType == TokenType::CooldownStart ? 5 : 2;
}
if (isInBounds(i + offset) && tokens[i + offset].tokenType == TokenType::QuestionEnd) {
break;
}
if (offset == 5 && tokens[i + 5].tokenType != TokenType::QuestionEnd) {
// Cannot place the identifier on the ordinary element.
return makeResult(
"Invalid identifier placement",
tokens[i]
);
}
}
// Determine element type.
bool isDash;
bool isGroup = false;
bool isOrder = false;
if (tokens[i].tokenType == TokenType::ElementDashStart) {
isDash = true;
} else {
isDash = false;
isPlusQuestion = true;
}
if (isInBounds(i+1) && tokens[i + 1].tokenType == TokenType::ElementOrderModifier) {
isOrder = true;
isOrderQuestion = true;
if (!isDash) {
return makeResult(
"order questions can only be used with dashes ('-')",
tokens[i]
);
}
if (isGroupQuestion) {
return makeResult(
"question with groups cannot be ordered ('-^' and ':')",
tokens[i]
);
}
if (isInBounds(i + 3) && tokens[i + 3].tokenType == TokenType::MatchGroupEnd) {
return makeResult(
"cannot have groups in order question('-^' and ':')",
tokens[i]
);
}
}
if (isInBounds(i + 2) && tokens[i + 2].tokenType == TokenType::MatchGroupEnd) {
isGroup = true;
isGroupQuestion = true;
if (!isDash) {
return makeResult(
"group questions can only be used with dashes ('-')",
tokens[i]
);
}
}
QuestionElement questionElement;
questionElement.isDash = isDash;
questionElement.isGroup = isGroup;
if (isOrder) {
questionElement.content = tokens[i + 2].content;
} else {
questionElement.content = tokens[i + 1].content;
}
questionElements.push_back(questionElement);
size_t offset = 2;
if (isOrder) {
offset += 1;
}
if (isGroup) {
offset += 1;
}
i += offset;
}
if (questionElements.size() > 0) {
if (isGroupQuestion) {
auto *question = new GroupQuestion();
question->cooldown = cooldown;
question->questionText = questionText;
question->section = section;
int32_t k = -1;
for (size_t i = 0; i < questionElements.size(); ++i) {
auto questionElement = questionElements[i];
if (questionElement.isGroup) {
++k;
auto group = Group();
group.name = cleanContent(questionElement.content);
question->groups.push_back(group);
} else {
if (k >= 0) {
question->groups[k].elements.push_back(
cleanContent(
questionElement.content
)
);
}
}
}
questions.push_back(question);
if (debug) {
std::cout << question->toString() << "\n";
}
} else {
auto *question = new MultiElementQuestion();
question->cooldown = cooldown;
question->questionText = cleanContent(questionText);
question->section = section;
for (const auto& elem : questionElements) {
Choice choice;
choice.answer = cleanContent(elem.content);
choice.isCorrect = !elem.isDash;
question->choices.push_back(choice);
}
questions.push_back(question);
if (isPlusQuestion) {
question->type = MultiElementType::MultiChoice;
} else if (isOrderQuestion) {
question->type = MultiElementType::Order;
} else {
question->type = MultiElementType::Regular;
}
if (debug) {
std::cout << question->toString() << "\n";
}
}
}
} else if (tokens[i].tokenType == TokenType::EndOfFile) {
if (debug) {
std::cout << "File terminated: EndOfFile\n";
}
break;
} else {
return makeResult(
"Unexpected token encountered",
tokens[i]
);
}
}
if (debug) {
std::cout << "SECTION END: Parser output:\n";
}
return makeResult(
"",
Token()
);
}
std::string MultiElementQuestion::toString() const {
std::stringstream ss;
for (const auto& choice : choices) {
char opener;
if (type == MultiElementType::Order) {
opener = '^';
} else if (choice.isCorrect) {
opener = '+';
} else {
opener = '-';
}
ss << opener << " " << choice.answer << "; ";
}
return std::format(
"<Multiple element>\nsection:{}\nid:{}\n{}\n{}",
section,
cooldown,
questionText,
ss.str()
);
}
std::string GroupQuestion::toString() const {
std::stringstream ss;
for (auto group: groups) {
ss << group.name << ": ";
for (auto el: group.elements) {
ss << el << ", ";
}
ss << "; ";
}
return std::format(
"<GroupQuestion>\nsection:{}\nid:{}\n{}\n{}",
section,
cooldown,
questionText,
ss.str()
);
}
```

View File

@@ -1,11 +1,12 @@
20.10.2024 13\:53
28.10.2024 17\:07
- [20.00] Arrange these events in the order they occurred >
- Arrange these events in the order they occurred >
-^ The Fall of the Roman
-^ The Renaissance
-^ The Industrial Revolution
-^ Step
- [19.70] Match Planets to Their Characteristics >
- [20.00] Match Planets to Their Characteristics >
- Earth:
- Contains Life
- Mars:
@@ -29,14 +30,13 @@
+ Poland
- China
- [44.91] What is the capital of Latvia? >
- [45.13] What is the capital of Latvia? >
- Rīga
- [44.91] What is the capital of Estonia? >
- [19.93] What is the capital of Estonia? >
- Tallin
- [1.20] Place the following steps of the scientific method in the
correct order >
- Place the following steps of the scientific method in the correct order >
-^ Ask a Question
-^ Form a Hypothesis
-^ Conduct an Experiment

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,43 @@
28.10.2024 08\:38
- Kā sauc Lietuvas galvaspilsētu >
- Viļņa
- Kā sauc Latvijas galvaspilsētu >
- Rīga
- Sakārtojiet zinātniskās metodes soļus pareizā secībā >
-^ Uzdod jautājumu
-^ Izvirza hipotēzi
-^ Veic eksperimentu
-^ Analizē datus
- [2.03] Sakārtojiet cilvēka gremošanas sistēmas posmus pareizā
secībā >
-^ Mutē ēdiens tiek sasmalcināts
-^ Norij un nonāk kuņģī
-^ Barība tiek sašķelta kuņģī
-^ Uzturvielas uzsūcas zarnās
-^ Atlikumi izvadīti caur taisno zarnu
- [10.50] Sakārtojiet fotosintēzes procesa posmus pareizā secībā
>
-^ Saules gaisma tiek uztverta ar hlorofilu
-^ Ūdens molekulas tiek sadalītas
-^ Tiek ražots skābeklis un glikoze
-^ Enerģija tiek uzkrāta glikozes veidā
- Sakārtojiet projekta izstrādes posmus pareizā secībā >
-^ Identificē prasības
-^ Veic plānošanu
-^ Īsteno izstrādi
-^ Testē un novērš kļūdas
-^ Nodod projektu lietošanai
- Sakārtojiet elektriskās ķēdes projektēšanas soļus pareizā
secībā >
-^ Izvēlas komponentus
-^ Izveido shēmas plānojumu
-^ Savieno komponentus shēmā
-^ Pārbauda un testē ķēdi

View File

@@ -0,0 +1,53 @@
26.10.2024 02\:33
- [12.50] Savienojiet dzīvniekus ar to īpašībām >
- Lauva:
- "Džungļu karalis"
- Zilonis:
- Lielākie sauszemes zīdītāji
- Garas ilknas
- Žirafe:
- Garākais sauszemes dzīvnieks
- Delfīns:
- Dzīvo ūdenī
- Gudri un sabiedriski
- Pingvīns:
- Dzīvo Antarktīdā
- Nespēj lidot
- Savienojiet valstis ar to ievērojamākajām ēkām >
- Francija:
- Eifeļa tornis
- Ēģipte:
- Gīzas piramīdas
- Ķīna:
- Lielais Ķīnas mūris
- Indija:
- Tadžmahals
- Itālija:
- Kolizejs
- Savienojiet zinātniekus ar to sasniegumiem >
- Alberts Einšteins:
- Relativitātes teorija
- Īzaks Ņūtons:
- Kustības likumi
- Nikola Tesla:
- Maiņstrāvas sistēma
- Luijs Pastērs:
- Vakcinācija un pasterizācija
- Galilejs Galilejs:
- Teleskopa uzlabojumi
- Savienojiet literatūras žanrus ar to īpašībām >
- Romāns:
- Garš stāstījums, bieži vien sarežģīta sižeta
- Dzeja:
- Rindas ar ritmisku struktūru
- Luga:
- Darbs, kas paredzēts izrādīšanai teātrī
- Eseja:
- Īss darbs ar autora personīgiem uzskatiem
- Novela:
- Īsāks par romānu, koncentrēts sižets

View File

@@ -0,0 +1,41 @@
26.10.2024 14\:22
- [20.00] Kā sauc Igaunijas galvaspilsētu? >
- Tallina
- Nosauciet Skandināvijas valstis >
- Zviedrija
- Norvēģija
- Dānija
- [12.49] Kā sauc Vācijas galvaspilsētu? >
- Berlīne
- Nosauciet Beneluksa valstis >
- Beļģija
- Nīderlande
- Luksemburga
- Kā sauc Francijas galvaspilsētu? >
- Parīze
- Nosauciet Apvienotās Karalistes valstis >
- Anglija
- Skotija
- Velsa
- Ziemeļīrija
- Ka sauc Lietuvas galvas pilsētu? >
- Viļņa
- Nosauciet Baltijas valstis >
- Latvija
- Igaunija
- Lietuva
- Kuras no valstīm ir Baltijas valstis >
+ Latvija
- Rumānija
+ Lietuva
- Spānija

58
resources/help.html Normal file
View File

@@ -0,0 +1,58 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<body>
<h1>Apmācība</h1>
<h2>Lietotnes nolūks</h2>
<p>
Lietotne "mdemory" ir dod iespēju mācīcies, izmantojot dažāda veida
atmiņas kartītes, ko var definēt un glabāt vienkāršā tekstā.
</p>
<h2>Atmiņas bāze</h2>
<p>
TODO
</p>
<h2>Kartīšu saraksts</h2>
<p>
TODO
</p>
<h2>Mācīšanās</h2>
<p>
TODO
</p>
<h2>Konfigurācija</h2>
<p>
TODO
</p>
<h2>Atmiņas kartīšu definēšana</h2>
<h3>Jautājumi</h3>
<h4>Atbildes jautājums</h4>
<p>
TODO
</p>
<h4>Izvēles jautājums</h4>
<p>
TODO
</p>
<h4>Secības jautājums</h4>
<p>
TODO
</p>
<h4>Grupēšanas jautājums</h4>
<p>
TODO
</p>
<h3>Datums un laiks</h3>
<p>
TODO
</p>
</body>
</html>

5
resources/resources.qrc Normal file
View File

@@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/html">
<file>help.html</file>
</qresource>
</RCC>

View File

@@ -16,13 +16,16 @@ find_package(Qt5 COMPONENTS Widgets REQUIRED)
# find_package(QScintilla REQUIRED)
include_directories(/usr/include/qt/Qsci)
qt5_add_resources(RESOURCES ${CMAKE_SOURCE_DIR}/resources/resources.qrc)
add_executable(
MdemoryApp
main.cpp
mdemList.cpp
trainWindow.cpp
settings.cpp
${RESOURCES}
)
target_link_libraries(MdemoryApp Qt5::Widgets /usr/lib/libqscintilla2_qt5.so api)
target_include_directories(MdemoryApp PRIVATE ${CMAKE_SOURCE_DIR}/include)
target_include_directories(MdemoryApp PRIVATE ${CMAKE_SOURCE_DIR}/src/include)

View File

@@ -62,6 +62,7 @@
#include <QStandardPaths>
#include <QShortcut>
#include <QWidget>
#include <QTextBrowser>
#include "config.h"
#include "settings.h"
@@ -780,17 +781,35 @@ QMainWindow *initMdemListWindow() {
pagination = new Pagination;
auto *toolbar = new Toolbar();
// Setup related windows
// Setup the related windows.
auto *settingsWindow = initSettings();
trainWindow = initTrainWindow();
QMainWindow *guideWindow = new QMainWindow;
{ // Guide window.
auto guideWidget = new QWidget;
auto *layout = new QVBoxLayout;
auto *textBrowser = new QTextBrowser;
textBrowser->setSource(QUrl("qrc:/html/help.html"));
textBrowser->zoomIn(2);
layout->addWidget(textBrowser);
guideWidget->setLayout(layout);
guideWindow->setCentralWidget(guideWidget);
}
QAction *actionOpen;
QAction *openSettings;
QAction *actionHelp;
{ // Menu bar.
QMenuBar *menuBar = new QMenuBar;
QFileDialog *fileDialog = new QFileDialog;
QMenu *menu = new QMenu("File");
QAction *actionOpen = menu->addAction("Open memorybase");
QObject::connect(actionOpen, &QAction::triggered, [fileDialog]() {
actionOpen = menu->addAction("Open memorybase");
QObject::connect(
actionOpen,
&QAction::triggered,
[fileDialog]() {
fileDialog->setDirectory(QDir::homePath());
fileDialog->setFileMode(QFileDialog::FileMode::Directory);
fileDialog->open();
@@ -800,9 +819,10 @@ QMainWindow *initMdemListWindow() {
&QFileDialog::fileSelected,
pickDirectory
);
});
}
);
QAction *openSettings = menu->addAction("Settings");
openSettings = menu->addAction("Settings");
QObject::connect(
openSettings,
&QAction::triggered,
@@ -810,6 +830,15 @@ QMainWindow *initMdemListWindow() {
settingsWindow->show();
});
actionHelp = menu->addAction("Help");
QObject::connect(
actionHelp,
&QAction::triggered,
[guideWindow]() {
guideWindow->show();
}
);
menuBar->addMenu(menu);
window->setMenuBar(menuBar);
}
@@ -1113,8 +1142,14 @@ QMainWindow *initMdemListWindow() {
});
};
addShortcut("Ctrl+,", [settingsWindow]() {
settingsWindow->show();
addShortcut("Ctrl+O", [actionOpen]() {
actionOpen->trigger();
});
addShortcut("Ctrl+H", [actionHelp]() {
actionHelp->trigger();
});
addShortcut("Ctrl+,", [openSettings]() {
openSettings->trigger();
});
addShortcut("Ctrl+S", [toolbar]() {
toolbar->btnSave.click();

View File

@@ -17,5 +17,5 @@ target_link_libraries(transpiler 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)
target_include_directories(transpiler PRIVATE ${CMAKE_SOURCE_DIR}/src/include)
target_include_directories(api PUBLIC ${CMAKE_SOURCE_DIR}/src/include)

View File

@@ -18,7 +18,7 @@ typedef std::map<TokenType, std::vector<TokenType>> TokenAutomata;
TokenAutomata *automata = nullptr;
/*
* Galīgs automāts, kas nosaka, kādā secībā ir var būt tekstvienības.
* Tekstvienību secības pārejas, kas nosaka, kādā secībā tekstvienības var būt.
* */
void initParserAutomata() {
automata = new TokenAutomata;

View File

@@ -1,48 +1,3 @@
- [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 >
- fiewfiwe
- kfoewf >
- fiewfiwe
- fewpfowe
- fweofopew
- ofpewpofkew
## Order question
- ewjpfwe >
^- ewijfew
^- ewijfew
^- ewijfew
^- ewijfew
^- ewijfew
## Match question
- iowjefew >
- fiwfo:
- fewfew
- ifoewf
- ejpfe:
- _
- fewfw:
- fewjpfe
- fioewf