Summary Files Commits Branches @commit @diff @stats
path: root / src
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 /src
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/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);
+ });
+ });
+});