Summary Files Commits Branches @commit @diff @stats
diff options
context:
space:
mode:
Commit7e77973c9d8594ee2f36a18b53f5d78d797a6686 (patch)
Author
 Syndamia <kamen@syndamia.com>
2025-10-05 20:31:09 +0300
Committer
 Syndamia <kamen@syndamia.com>
2025-10-05 20:31:09 +0300
Files8fc21d33f95d5a9ea99fe5b436a8bd71b57759c8
syndamia.com-7e77973c9d8594ee2f36a18b53f5d78d797a6686.tar
syndamia.com-7e77973c9d8594ee2f36a18b53f5d78d797a6686.tar.gz
syndamia.com-7e77973c9d8594ee2f36a18b53f5d78d797a6686.zip
Parentaf0d8026bad910e98b04f760a8d836ede8b6a1cd (diff)
feat(teaching/upp-2025/w02): Add materials and exercises
This week will be very experimental, since no real material will be taught. We could do some git or Visual Studio drills but those will be boring and limited in useability. Using this fancy table should aid in pointers and thinking about data and operations as part of the same domain.
diff --git a/dunbar b/dunbar
-Subproject 2ba70d193b4001ca2ec6c9d3ade235d9b3ba7d4
+Subproject 7455535abb512e75ba1d1c7032e7aecf54707b1
diff --git a/meta/meta.tsv b/meta/meta.tsv
index 1aad9c1..4762ab2 100644
--- a/meta/meta.tsv
+++ b/meta/meta.tsv
@@ -94,6 +94,10 @@ teaching/upp-2025/week01/github_classroom.html GitHub Classroom упътване
teaching/upp-2025/week01/introduction.html Уводни бележки - УПП, Седмица 1, 02.10.2025 Бележки относно практикума и курса.
teaching/upp-2025/week01/visual_studio.html Visual Studio упътване - УПП, Седмица 1, 02.10.2025 Упътване как да инсталирате, настроите и използвате Visual Studio.
teaching/upp-2025/week01/zip.html ZIP архиви упътване - УПП, Седмица 1, 02.10.2025 Упътване какво да инсталирате за създаване на ZIP архиви и как да ги създадете.
+teaching/upp-2025/week02/machine.html Машинна таблица - УПП, Седмица 2, 09.10.2025 Страница където може да работите с машинната таблица
+teaching/upp-2025/week02/index.html Задачи - УПП, Седмица 2, 09.10.2025 Условията на задачите за упражнение.
+teaching/upp-2025/week02/machine_manual.html Упътване на машинната таблица - УПП, Седмица 2, 09.10.2025 Какво е машинната таблица, как работи, какви команди поддържа.
+teaching/upp-2025/week02/machine_table.html Машинна таблица - УПП, Седмица 2, 09.10.2025 Страница където може да работите с машинната таблица.
blog/connect-to-mysql-in-dotnet-ef/index.html Connect to MySql in .NET and Entity Framework Connecting a .NET application to a MySql database (with Entity Framework) can be tricky. Here is what works for me.
diff --git a/src/teaching/upp-2025/index.du b/src/teaching/upp-2025/index.du
index 3b4576a..60a5ba9 100644
--- a/src/teaching/upp-2025/index.du
+++ b/src/teaching/upp-2025/index.du
@@ -22,5 +22,15 @@
[url ./week01/introduction.html?a Уводни бележки] || [url ./week01/concepts.html?a Общи концепции] || [url ./week01/github_classroom.html?a GitHub Classroom упътване] || [url ./week01/visual_studio.html?a Visual Studio упътване] || <br>[url ./week01/zip.html?a ZIP архиви упътване]
:|
|::||::||:
- [url ./week01/index.html Задачи] || [url https://classroom.github.com/a/-1l498jX GitHub Classroom]
+ [url ./week01 Задачи] || [url https://classroom.github.com/a/-1l498jX GitHub Classroom]
+ :|
+
+|:2:|
+ |:09.10.2025:|
+ |:Програмистко мислене *[(много експериментално)]*:|
+|::||::||:
+ [url ./week02/machine_manual.html?a Упътване на машинната таблица] || [url ./week02/machine.html?a Машинна таблица]
+ :|
+|::||::||:
+ [url ./week02 Задачи] || [url https://classroom.github.com/a/DRjtkc6f GitHub Classroom]
:|
diff --git a/src/teaching/upp-2025/week02/img/machine_table.png b/src/teaching/upp-2025/week02/img/machine_table.png
new file mode 100644
index 0000000..56ce787
--- /dev/null
+++ b/src/teaching/upp-2025/week02/img/machine_table.png
Binary files differ
diff --git a/src/teaching/upp-2025/week02/img/table_ashow.gif b/src/teaching/upp-2025/week02/img/table_ashow.gif
new file mode 100644
index 0000000..017da4a
--- /dev/null
+++ b/src/teaching/upp-2025/week02/img/table_ashow.gif
Binary files differ
diff --git a/src/teaching/upp-2025/week02/img/table_ashow_and_asum.gif b/src/teaching/upp-2025/week02/img/table_ashow_and_asum.gif
new file mode 100644
index 0000000..d40d417
--- /dev/null
+++ b/src/teaching/upp-2025/week02/img/table_ashow_and_asum.gif
Binary files differ
diff --git a/src/teaching/upp-2025/week02/img/table_asubtract.gif b/src/teaching/upp-2025/week02/img/table_asubtract.gif
new file mode 100644
index 0000000..a114842
--- /dev/null
+++ b/src/teaching/upp-2025/week02/img/table_asubtract.gif
Binary files differ
diff --git a/src/teaching/upp-2025/week02/img/table_asum.gif b/src/teaching/upp-2025/week02/img/table_asum.gif
new file mode 100644
index 0000000..ecb5e6f
--- /dev/null
+++ b/src/teaching/upp-2025/week02/img/table_asum.gif
Binary files differ
diff --git a/src/teaching/upp-2025/week02/img/table_asum_input1.gif b/src/teaching/upp-2025/week02/img/table_asum_input1.gif
new file mode 100644
index 0000000..da8128d
--- /dev/null
+++ b/src/teaching/upp-2025/week02/img/table_asum_input1.gif
Binary files differ
diff --git a/src/teaching/upp-2025/week02/img/table_asum_input1_input2.gif b/src/teaching/upp-2025/week02/img/table_asum_input1_input2.gif
new file mode 100644
index 0000000..ad5806c
--- /dev/null
+++ b/src/teaching/upp-2025/week02/img/table_asum_input1_input2.gif
Binary files differ
diff --git a/src/teaching/upp-2025/week02/img/table_execution_continuous.gif b/src/teaching/upp-2025/week02/img/table_execution_continuous.gif
new file mode 100644
index 0000000..9bf6a9d
--- /dev/null
+++ b/src/teaching/upp-2025/week02/img/table_execution_continuous.gif
Binary files differ
diff --git a/src/teaching/upp-2025/week02/img/table_execution_empty.gif b/src/teaching/upp-2025/week02/img/table_execution_empty.gif
new file mode 100644
index 0000000..e2988c2
--- /dev/null
+++ b/src/teaching/upp-2025/week02/img/table_execution_empty.gif
Binary files differ
diff --git a/src/teaching/upp-2025/week02/img/table_gotobz.gif b/src/teaching/upp-2025/week02/img/table_gotobz.gif
new file mode 100644
index 0000000..cbd3df8
--- /dev/null
+++ b/src/teaching/upp-2025/week02/img/table_gotobz.gif
Binary files differ
diff --git a/src/teaching/upp-2025/week02/img/table_gotobz_false.gif b/src/teaching/upp-2025/week02/img/table_gotobz_false.gif
new file mode 100644
index 0000000..5c9ff19
--- /dev/null
+++ b/src/teaching/upp-2025/week02/img/table_gotobz_false.gif
Binary files differ
diff --git a/src/teaching/upp-2025/week02/index.du b/src/teaching/upp-2025/week02/index.du
new file mode 100644
index 0000000..a294936
--- /dev/null
+++ b/src/teaching/upp-2025/week02/index.du
@@ -0,0 +1,61 @@
+# Задачи - УПП, Седмица 2, 09.10.2025
+
+'define expected-reading 2 min
+'define created 05 October 2025
+'define edited 05 October 2025
+[$pagenav]
+
+.warn
+Всички задачи от днес са върху [url ./machine.html "машинната таблица"].
+
+GitHub Classroom: [url https://classroom.github.com/a/DRjtkc6f]
+
+## Задача 1
+
+Покажете числото 1337 в "popup".
+
+## Задача 2
+
+Покажете сумата на `[INPUT1]` и 8 в "popup".
+
+## Задача 3
+
+Покажете числото `[INPUT1]` в "popup", но с обърнат знак.
+
+## Задача 4
+
+Покажете `[INPUT1]` умножено по две в "popup".
+
+## Задача 5
+
+Ако `[INPUT1]` е равно на 10, покажете в "popup" стойността 1.
+Иначе, покажете стойността 0.
+
+## Задача 6
+
+Покажете в "popup" числото 1 ако `[INPUT1]` =[или]= `[INPUT2]` е равно на 5.
+Иначе покажете 0.
+
+## Задача 7
+
+Покажете в "popup" числото 1 ако `[INPUT1]` =[и]= `[INPUT2]` са равни на 5.
+Иначе покажете 0.
+
+## Задача 8
+
+Покажете в "popup" умножението на `[INPUT1]` и `[INPUT2]`.
+Допускаме, че `[INPUT2]` е неотрицателно цяло число.
+
+## Задача 9
+
+Нека `[INPUT1]` да обозначава разликата на аритметична прогресия (разликата между два съседни елементa) и `[INPUT2]` да обозначава индекса на елемент в тази прогресия.
+
+Покажаете в "popup" числото на `[INPUT2]` позиция от аритметичната прогресия.
+Нека първия елемент винаги е 0 и неговия индекс е 1.
+
+Допускаме, че `[INPUT2]` е неотрицателно цяло число.
+
+## Задача 10
+
+Покажете в "popup" делението на `[INPUT1]` и `[INPUT2]`, закръглено нагоре.
+Допускаме, че `[INPUT2]` е неотрицателно цяло число.
diff --git a/src/teaching/upp-2025/week02/machine.du b/src/teaching/upp-2025/week02/machine.du
new file mode 100644
index 0000000..7dda64f
--- /dev/null
+++ b/src/teaching/upp-2025/week02/machine.du
@@ -0,0 +1,43 @@
+# Машинна таблица - УПП, Седмица 2, 09.10.2025
+
+'define expected-reading 2 min
+'define created 05 October 2025
+'define edited 05 October 2025
+[$pagenav]
+
+В тази таблица може да редактирате клетките на колона A и тези срещу INPUT1 и INPUT2.
+
+При изпълнение, всяка клетка в A се обикаля отгоре-надолу (показано с жълто).
+Ако срещне =[команда]= тогава потенциално прочита и долната клетка, и извършва някакво действие.
+
+Повече подробности в [url ./machine_manual.html упътването].
+Списък от налични команди [url #section-1 в дъното на страницата].
+
+.text
+'snippet 8 $ ./machine_table.html
+
+## Команди
+
+:defs
+; `[ASUM]`
+: Прави `[A = A + <числото в долната клетка>]`
+
+; `[ASUBTRACT]`
+: Прави `[A = A - <числото в долната клетка>]`
+
+; `[ASHOW]`
+: Показва стойността на `[A]` като pop-up.
+
+; `[BSUM]`
+: Прави `[B = B + <числото в долната клетка>]`
+
+; `[BSUBTRACT]`
+: Прави `[B = B - <числото в долната клетка>]`
+
+; `[GOTOBZ]`
+: Ако `[B]` =[е]= 0, тогава отива на реда, посочен от следващата клетка.
+ Иначе продължава нататък.
+
+; `[GOTOBN]`
+: Ако `[B]` =[не е]= 0, тогава отива на реда, посочен от следващата клетка.
+ Иначе продължава нататък.
diff --git a/src/teaching/upp-2025/week02/machine_manual.du b/src/teaching/upp-2025/week02/machine_manual.du
new file mode 100644
index 0000000..acf5559
--- /dev/null
+++ b/src/teaching/upp-2025/week02/machine_manual.du
@@ -0,0 +1,202 @@
+# Упътване на машинната таблица - УПП, Седмица 2, 09.10.2025
+
+'define expected-reading 3 min
+'define created 05 October 2025
+'define edited 05 October 2025
+[$pagenav]
+
+[$presentation-controller]
+
+:title_slide35
+
+# Машинна таблица
+
+
+:middle_slide35
+
+.unordered
+- Целта е да разиграем мисленето за програмиране
+- Без да пишем истински код
+- "Машинната таблица" е специална таблица, която създадох за този практикум\n
+ *[(щеше да е на Excel ама...)]*
+- Тя симулира действието на един =[много]= прост компютър
+
+
+:slide35
+
+## Принцип на действие
+
+.centered
+[image ./img/machine_table.png]
+
+
+:middle_slide35
+
+.p
+Когато натиснем "Изпълни", започва да се движи от A1 до A15
+
+.centered
+.font18
+*[(По принцип ще спре при първия празен ред)]*
+
+.centered
+.p
+[image ./img/table_execution_continuous.gif]
+
+
+:middle_slide35
+
+.centered
+.p
+Продължава да обикаля клетки, докато не срещне =[празна клетка]= или не свършат всички клетки
+
+.centered
+.p
+[image ./img/table_execution_empty.gif]
+
+
+:middle_slide35
+
+.unordered
+- Във всяка една клетка може да срещне =[команда]= или =[число]=
+- Очаква последователност от команди в колона A
+- След =[някои]= команди, може да се срещне и число
+- Стойности могат да се въвеждат в колоната A
+- Клетките "A" и "B" стават 0 при изпълнение
+- Всяка команда работи със стойността на клетката "A" =[или]= "B"
+
+
+:middle_slide35
+
+## Командата `[ASHOW]`
+
+.p
+Показва стойността на клетката A като popup
+
+.p
+[image ./img/table_ashow.gif]
+
+
+:middle_slide35
+
+## Командата `[ASUM]`
+
+.p
+Поглежда числото в долната клетка и го сумира към клетката "А".
+
+.p
+[image ./img/table_asum.gif]
+
+
+:middle_slide35
+
+### Минизадача
+
+.p
+Нека да покажем "A", добавим 5 към него и пак го покажем
+
+.p
+[image ./img/table_ashow_and_asum.gif]
+
+
+:middle_slide35
+
+## Командата `[ASUBTRACT]`
+
+.p
+Като `[ASUM]`, но изважда вместо да събере.
+
+.p
+[image ./img/table_asubtract.gif]
+
+
+:middle_slide35
+
+## INPUT клетките
+
+.unordered
+- Освен числови константи, за числа се зачитат и "INPUT1" и "INPUT2"
+- Те се заместват със стойността срещу съответната клетка
+
+
+:middle_slide35
+
+### Минизадача
+
+.p
+Нека да добавим стойността на INPUT1 към "A"
+
+.p
+[image ./img/table_asum_input1.gif]
+
+
+:middle_slide35
+
+### Минизадача
+
+.p
+Нека добавим стойността на INPUT1 и INPUT2 към "А"
+
+.p
+[image ./img/table_asum_input1_input2.gif]
+
+
+:middle_slide35
+
+## Командата `[BSUM]`
+
+.p
+Същото като `[ASUM]`, но с клетка "B".
+
+## Командата `[BSUBTRACT]`
+
+.p
+Същото като `[ASUBTRACT]`, но с клетка "B".
+
+[$br1]
+
+.p
+=[Нямаме `[BSHOW]`!]=
+Но имаме други специални команди.
+
+
+:middle_slide35
+
+## Командата `[GOTOBZ]`
+
+.p
+=[Ако]= клетка "B" е равна на 0, тогава прочита следващата клетка и отива на посочения ред.
+
+.p
+[image ./img/table_gotobz.gif]
+
+
+:middle_slide
+
+.p
+=[Иначе]= продължава напред
+
+.p
+[image ./img/table_gotobz_false.gif]
+
+
+:middle_slide35
+
+## Командата `[GOTOBN]`
+
+.p
+Същата като `[GOTOBZ]`, обаче отива на посочения ред когато "B" е =[по-голямо или равно]= на 0 (неотрицателно).
+
+
+:middle_slide35
+
+.unordered
+- Употребата на останалите бутони трябва да е явна.
+- "Запази" запазва =[само]= колона A!
+
+
+:middle_slide35
+
+.p
+.centered
+[url ./index.html Към задачите]
diff --git a/src/teaching/upp-2025/week02/machine_table.html b/src/teaching/upp-2025/week02/machine_table.html
new file mode 100644
index 0000000..bf1a6cd
--- /dev/null
+++ b/src/teaching/upp-2025/week02/machine_table.html
@@ -0,0 +1,125 @@
+<h1>Машинна таблица - УПП, Седмица 2, 09.10.2025</h1>
+<p>
+ <a href="./machine_manual.html?a">Упътване</a>
+ &ensp;||&ensp;
+ <a href="./index.html">Задачи</a>
+</p>
+<br/>
+
+<table id="worksheet">
+ <tr>
+ <th></th>
+ <th>A</th>
+ <th>B</th>
+ <th>C</th>
+ </tr>
+ <tr>
+ <th>1</th><td spellcheck="false" contenteditable="true"></td>
+ <td><button id="save">Запази</button></td>
+ <td><button id="load">Зареди</button></td>
+ </tr>
+ <tr>
+ <th>2</th><td spellcheck="false" contenteditable="true"></td>
+ <td>INPUT1:</td><td id="input1" spellcheck="false" contenteditable="true"></td>
+ </tr>
+ <tr>
+ <th>3</th><td spellcheck="false" contenteditable="true"></td>
+ <td>INPUT2:</td><td id="input2" spellcheck="false" contenteditable="true"></td>
+ </tr>
+ <tr>
+ <th>4</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>5</th><td spellcheck="false" contenteditable="true"></td>
+ <td>A:</td><td id="regA">0</td>
+ </tr>
+ <tr>
+ <th>6</th><td spellcheck="false" contenteditable="true"></td>
+ <td>B:</td><td id="regB">0</td>
+ </tr>
+ <tr>
+ <th>7</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>8</th><td spellcheck="false" contenteditable="true"></td>
+ <td><button id="execute">Изпълни</button></td>
+ <td>
+ <input type="radio" id="speedChoice1" name="speed" value="250" />
+ <label for="speedChoice1">Бързо</label>
+
+ <input type="radio" id="speedChoice2" name="speed" value="1000" checked />
+ <label for="speedChoice2">Бавно</label>
+ </td>
+ </tr>
+ <tr>
+ <th>9</th><td spellcheck="false" contenteditable="true"></td>
+ <td><button id="stopresume">Спри</button></td><td></td>
+ </tr>
+ <tr>
+ <th>10</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>11</th><td spellcheck="false" contenteditable="true"></td>
+ <td>Грешка:</td><td id="errorMsg"></td>
+ </tr>
+ <tr>
+ <th>12</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>13</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>14</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>15</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>16</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>17</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>18</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>19</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>20</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>21</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>22</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>23</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>24</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+ <tr>
+ <th>25</th><td spellcheck="false" contenteditable="true"></td>
+ <td></td><td></td>
+ </tr>
+</table>
+<script type="text/javascript" src="./machine_table.js" crossorigin="anonymous" defer></script>
diff --git a/src/teaching/upp-2025/week02/machine_table.js b/src/teaching/upp-2025/week02/machine_table.js
new file mode 100644
index 0000000..ec67ff8
--- /dev/null
+++ b/src/teaching/upp-2025/week02/machine_table.js
@@ -0,0 +1,339 @@
+// Style //
+
+var machineStyles = document.createElement("style");
+machineStyles.textContent = `
+ /* Reset */
+ #worksheet table,
+ #worksheet tr,
+ #worksheet th,
+ #worksheet td {
+ background-color: initial;
+ border: initial;
+ padding: 0.1em;
+ }
+
+ /* General styling */
+ #worksheet th {
+ font-weight: normal;
+ }
+ #worksheet {
+ color: black;
+ background-color: white;
+ margin: 1em auto;
+
+ /* Thanks https://stackoverflow.com/a/4407335/12036073 */
+
+ -webkit-touch-callout: none; /* iOS Safari */
+ -webkit-user-select: none; /* Safari */
+ -khtml-user-select: none; /* Konqueror HTML */
+ -moz-user-select: none; /* Old versions of Firefox */
+ -ms-user-select: none; /* Internet Explorer/Edge */
+ user-select: none;
+ }
+
+ #worksheet button {
+ border-radius: 0;
+ border-width: 2px;
+ width: 100%;
+ }
+ #worksheet button:hover,
+ #worksheet input[type="radio"]:hover,
+ #worksheet input[type="radio"] ~ label:hover {
+ cursor: pointer;
+ }
+
+ /* Borders and colors */
+ #worksheet td, #worksheet th {
+ border: 1px solid #c0c0c0;
+ }
+ #worksheet tr:first-of-type th,
+ #worksheet td:first-child, #worksheet th:first-child
+ {
+ border-color: #6a6a6a;
+ background-color: #f1f1f1;
+ }
+ #worksheet tr:first-of-type th {
+ border-top: none;
+ }
+ #worksheet td:first-child, #worksheet th:first-child {
+ border-left: none;
+ }
+
+ /* Spacing */
+ #worksheet th:first-child {
+ min-width: 2.82em;
+ padding: 0.3em 0;
+ }
+ #worksheet td {
+ min-width: 8em;
+ padding: 0.3em 0.2em;
+ }
+
+ #worksheet button {
+ margin: calc(-0.3em + 4px) 0;
+ padding: 0.2em;
+ }
+
+ /* Execution */
+ .selected {
+ background-color: yellow !important;
+ }
+ .error {
+ background-color: red !important;
+ }
+`;
+document.head.appendChild(machineStyles);
+
+// Execution //
+
+const INPUT1 = document.getElementById("input1");
+const INPUT2 = document.getElementById("input2");
+const A = document.getElementById("regA");
+const B = document.getElementById("regB");
+
+const errorMsg = document.getElementById("errorMsg");
+
+var speed = 1000;
+var running = false;
+var stop = false;
+
+const memory = document.querySelectorAll("#worksheet tr:not(:first-of-type) > td:first-of-type");
+var memoryLocation = memory.length;
+var parametrisedCommand = null;
+
+function executeInit() {
+ running = true;
+ A.innerText = 0;
+ B.innerText = 0;
+ errorMsg.innerText = '';
+
+ for (let i = 0; i < memory.length; ++i) {
+ memory[i].innerText = memory[i].innerText
+ .trim()
+ .replace(' ', '')
+ .replace('\n', '');
+ memory[i].classList.remove('error');
+ memory[i].classList.remove('selected');
+ }
+}
+
+function executeDeinit() {
+ memoryLocation = memory.length;
+ parametrisedCommand = null;
+ stop = false;
+ running = false;
+ stopresumeBtn.innerText = 'Спри';
+}
+
+function expectedCommand() {
+ if (parametrisedCommand !== null) {
+ error('Очакваше се число, не команда!');
+ return false;
+ }
+ return true;
+}
+
+function expectedNumber() {
+ if (parametrisedCommand === null) {
+ error('Очакваше се команда!');
+ return false;
+ }
+ if (isNaN(toNumber(memory[memoryLocation].innerText))) {
+ error('Очакваше се валидно число!');
+ return false;
+ }
+ return true;
+}
+
+function error(msg) {
+ errorMsg.innerText = msg;
+ memory[memoryLocation].classList.add('error');
+ executeDeinit();
+}
+
+function toNumber(text) {
+ if (text === 'INPUT1') text = INPUT1.innerText;
+ else if (text === 'INPUT2') text = INPUT2.innerText;
+
+ return Number(text);
+}
+
+function execute() {
+ if (stop) {
+ running = false;
+ return;
+ }
+
+ // After cell was set
+ if (memoryLocation < memory.length) {
+ memory[memoryLocation].classList.remove('selected');
+
+ switch (parametrisedCommand) {
+ case null: break;
+ case 'ASUM':
+ if (!expectedNumber()) return;
+ A.innerText = Number(A.innerText) + toNumber(memory[memoryLocation].innerText);
+ break;
+ case 'ASUBTRACT':
+ if (!expectedNumber()) return;
+ A.innerText = Number(A.innerText) - toNumber(memory[memoryLocation].innerText);
+ break;
+ case 'BSUM':
+ if (!expectedNumber()) return;
+ B.innerText = Number(B.innerText) + toNumber(memory[memoryLocation].innerText);
+ break;
+ case 'BSUBTRACT':
+ if (!expectedNumber()) return;
+ B.innerText = Number(B.innerText) - toNumber(memory[memoryLocation].innerText);
+ break;
+ case 'GOTOBZ':
+ if (!expectedNumber()) return;
+ if (Number(B.innerText) === 0)
+ memoryLocation = toNumber(memory[memoryLocation].innerText) - 2;
+ break;
+ case 'GOTOBN':
+ if (!expectedNumber()) return;
+ if (Number(B.innerText) >= 0)
+ memoryLocation = toNumber(memory[memoryLocation].innerText) - 2;
+ break;
+ }
+
+ if (parametrisedCommand === null) {
+ switch (memory[memoryLocation].innerText) {
+ case '':
+ executeDeinit();
+ return;
+ case 'ASHOW':
+ alert(A.innerText);
+ break;
+ case 'ASUM':
+ case 'ASUBTRACT':
+ case 'GOTOBZ':
+ case 'GOTOBN':
+ case 'BSUM':
+ case 'BSUBTRACT':
+ if (!expectedCommand()) return;
+ parametrisedCommand = memory[memoryLocation].innerText;
+ break;
+ default:
+ error('Невалидна команда!');
+ return;
+ }
+ }
+ else parametrisedCommand = null;
+ }
+ // On execution start
+ else {
+ executeInit();
+ }
+
+ memoryLocation = (memoryLocation + 1) % (memory.length + 1);
+ memory[memoryLocation].classList.add('selected');
+
+ if (memoryLocation < memory.length) {
+ setTimeout(execute, speed);
+ }
+}
+
+const execBtn = document.getElementById("execute");
+execBtn.addEventListener('click', function() {
+ if (!running)
+ executeDeinit();
+ if (memoryLocation == memory.length)
+ execute();
+});
+
+const stopresumeBtn = document.getElementById('stopresume');
+stopresumeBtn.addEventListener('click', function() {
+ if (stop && !running) {
+ stop = false;
+ running = true;
+ stopresumeBtn.innerText = 'Спри';
+ execute();
+ }
+ else if (!stop && running) {
+ stop = true;
+ stopresumeBtn.innerText = 'Продължи';
+ }
+});
+
+// Disallow newline
+function preventCharacters(evt) {
+ if (evt.keyCode == 13 || evt.keyCode == 32)
+ evt.preventDefault();
+}
+for (let i = 0; i < memory.length; ++i) {
+ memory[i].addEventListener('keydown', preventCharacters);
+}
+
+// Speed //
+
+const rbFast = document.getElementById('speedChoice1');
+const rbSlow = document.getElementById('speedChoice2');
+
+rbFast.addEventListener('change', function() {
+ speed = rbFast.value;
+});
+if (rbFast.checked) speed = rbFast.value;
+
+rbSlow.addEventListener('change', function() {
+ speed = rbSlow.value;
+});
+if (rbSlow.checked) speed = rbSlow.value;
+
+// Save/load //
+
+const saveBtn = document.getElementById('save');
+const loadBtn = document.getElementById('load');
+
+saveBtn.addEventListener('click', function() {
+ let contents = '';
+ for (let i = 0; i < memory.length; ++i) {
+ contents += memory[i].innerText + '\n';
+ }
+
+ let now = new Date();
+ let datetime =
+ now.getFullYear().toString()
+ + (now.getMonth() < 10 ? '0' : '')
+ + now.getMonth().toString()
+ + (now.getDate() < 10 ? '0' : '')
+ + now.getDate()
+ + "_"
+ + now.getHours()
+ + now.getMinutes();
+
+ // Thanks https://stackoverflow.com/a/79383186
+ const download = document.createElement('a');
+ download.href = URL.createObjectURL(new Blob([contents], { type: 'text/csv' }));
+ download.download = 'Таблица_' + datetime + '.csv';
+ download.click();
+
+ URL.revokeObjectURL(download.href);
+});
+
+function loadMemory(text) {
+ let rows = text.split("\n");
+ for (let i = 0; i < memory.length; ++i) {
+ memory[i].innerText = rows[i].split(',')[0];
+ }
+}
+
+loadBtn.addEventListener('click', function() {
+ const upload = document.createElement('input');
+ upload.type = 'file';
+ upload.accept = 'text/csv';
+ upload.click();
+
+ upload.addEventListener('change', function(e) {
+ let file = e.target.files[0];
+ if (!file) return;
+
+ let reader = new FileReader();
+ reader.readAsText(file);
+
+ reader.addEventListener('load', function(e) {
+ loadMemory(e.target.result);
+ });
+ });
+});