munchboka-edutools 0.2.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of munchboka-edutools might be problematic. Click here for more details.

Files changed (157) hide show
  1. munchboka_edutools/__init__.py +184 -0
  2. munchboka_edutools/_plotmath_shim.py +126 -0
  3. munchboka_edutools/_version.py +2 -0
  4. munchboka_edutools/directives/__init__.py +1 -0
  5. munchboka_edutools/directives/admonitions.py +389 -0
  6. munchboka_edutools/directives/cas_popup.py +428 -0
  7. munchboka_edutools/directives/clear.py +103 -0
  8. munchboka_edutools/directives/dialogue.py +137 -0
  9. munchboka_edutools/directives/escape_room.py +296 -0
  10. munchboka_edutools/directives/escape_room2.py +318 -0
  11. munchboka_edutools/directives/factor_tree.py +552 -0
  12. munchboka_edutools/directives/flashcards.py +233 -0
  13. munchboka_edutools/directives/ggb.py +209 -0
  14. munchboka_edutools/directives/ggb_icon.py +105 -0
  15. munchboka_edutools/directives/ggb_popup.py +308 -0
  16. munchboka_edutools/directives/horner.py +326 -0
  17. munchboka_edutools/directives/interactive_code.py +75 -0
  18. munchboka_edutools/directives/jeopardy.py +252 -0
  19. munchboka_edutools/directives/jeopardy2.py +636 -0
  20. munchboka_edutools/directives/multi_plot.py +2524 -0
  21. munchboka_edutools/directives/multi_plot2.py +252 -0
  22. munchboka_edutools/directives/pair_puzzle.py +191 -0
  23. munchboka_edutools/directives/parsons.py +109 -0
  24. munchboka_edutools/directives/plot.py +3758 -0
  25. munchboka_edutools/directives/poly_icon.py +111 -0
  26. munchboka_edutools/directives/polydiv.py +346 -0
  27. munchboka_edutools/directives/popup.py +245 -0
  28. munchboka_edutools/directives/quiz.py +291 -0
  29. munchboka_edutools/directives/quiz2.py +453 -0
  30. munchboka_edutools/directives/signchart.py +519 -0
  31. munchboka_edutools/directives/signchart2.py +1545 -0
  32. munchboka_edutools/directives/timed_quiz.py +436 -0
  33. munchboka_edutools/directives/turtle.py +157 -0
  34. munchboka_edutools/static/css/admonitions.css +2012 -0
  35. munchboka_edutools/static/css/cas_popup.css +242 -0
  36. munchboka_edutools/static/css/code_mirror_themes/github_dark_cm.css +112 -0
  37. munchboka_edutools/static/css/code_mirror_themes/github_dark_default_cm.css +40 -0
  38. munchboka_edutools/static/css/code_mirror_themes/github_dark_high_contrast_cm.css +141 -0
  39. munchboka_edutools/static/css/code_mirror_themes/github_light_cm.css +120 -0
  40. munchboka_edutools/static/css/code_mirror_themes/github_light_default_cm.css +108 -0
  41. munchboka_edutools/static/css/code_mirror_themes/one_dark_cm.css +121 -0
  42. munchboka_edutools/static/css/dialogue.css +92 -0
  43. munchboka_edutools/static/css/escapeRoom/escape-room.css +223 -0
  44. munchboka_edutools/static/css/figures.css +321 -0
  45. munchboka_edutools/static/css/flashcards.css +219 -0
  46. munchboka_edutools/static/css/general_style.css +74 -0
  47. munchboka_edutools/static/css/github-dark-high-contrast.css +141 -0
  48. munchboka_edutools/static/css/github-dark.css +147 -0
  49. munchboka_edutools/static/css/github-light.css +155 -0
  50. munchboka_edutools/static/css/interactive_code/style.css +575 -0
  51. munchboka_edutools/static/css/interactive_code.css +582 -0
  52. munchboka_edutools/static/css/jeopardy.css +553 -0
  53. munchboka_edutools/static/css/pairPuzzle/style.css +177 -0
  54. munchboka_edutools/static/css/parsons/parsonsPuzzle.css +331 -0
  55. munchboka_edutools/static/css/popup.css +115 -0
  56. munchboka_edutools/static/css/quiz.css +377 -0
  57. munchboka_edutools/static/css/timedQuiz.css +375 -0
  58. munchboka_edutools/static/icons/ggb/mode_evaluate.svg +1 -0
  59. munchboka_edutools/static/icons/ggb/mode_extremum.svg +1 -0
  60. munchboka_edutools/static/icons/ggb/mode_intersect.svg +1 -0
  61. munchboka_edutools/static/icons/ggb/mode_nsolve.svg +1 -0
  62. munchboka_edutools/static/icons/ggb/mode_numeric.svg +1 -0
  63. munchboka_edutools/static/icons/ggb/mode_point.svg +1 -0
  64. munchboka_edutools/static/icons/ggb/mode_solve.svg +1 -0
  65. munchboka_edutools/static/icons/misc/windows-logo.svg +1 -0
  66. munchboka_edutools/static/icons/outline/dark_mode/academic.svg +3 -0
  67. munchboka_edutools/static/icons/outline/dark_mode/backward.svg +3 -0
  68. munchboka_edutools/static/icons/outline/dark_mode/book.svg +3 -0
  69. munchboka_edutools/static/icons/outline/dark_mode/chat_bubble.svg +3 -0
  70. munchboka_edutools/static/icons/outline/dark_mode/check.svg +3 -0
  71. munchboka_edutools/static/icons/outline/dark_mode/cmd_line.svg +3 -0
  72. munchboka_edutools/static/icons/outline/dark_mode/file.svg +1 -0
  73. munchboka_edutools/static/icons/outline/dark_mode/fire.svg +4 -0
  74. munchboka_edutools/static/icons/outline/dark_mode/key.svg +3 -0
  75. munchboka_edutools/static/icons/outline/dark_mode/magnifying.svg +3 -0
  76. munchboka_edutools/static/icons/outline/dark_mode/pencil_square.svg +3 -0
  77. munchboka_edutools/static/icons/outline/dark_mode/play.svg +3 -0
  78. munchboka_edutools/static/icons/outline/dark_mode/question.svg +3 -0
  79. munchboka_edutools/static/icons/outline/dark_mode/square_check.svg +1 -0
  80. munchboka_edutools/static/icons/outline/dark_mode/stop.svg +3 -0
  81. munchboka_edutools/static/icons/outline/dark_mode/summary.svg +3 -0
  82. munchboka_edutools/static/icons/outline/dark_mode/undo.svg +3 -0
  83. munchboka_edutools/static/icons/outline/dark_mode/unlock.svg +3 -0
  84. munchboka_edutools/static/icons/outline/light_mode/academic.svg +3 -0
  85. munchboka_edutools/static/icons/outline/light_mode/backward.svg +3 -0
  86. munchboka_edutools/static/icons/outline/light_mode/book.svg +3 -0
  87. munchboka_edutools/static/icons/outline/light_mode/chat_bubble.svg +3 -0
  88. munchboka_edutools/static/icons/outline/light_mode/check.svg +3 -0
  89. munchboka_edutools/static/icons/outline/light_mode/cmd_line.svg +3 -0
  90. munchboka_edutools/static/icons/outline/light_mode/file.svg +1 -0
  91. munchboka_edutools/static/icons/outline/light_mode/fire.svg +4 -0
  92. munchboka_edutools/static/icons/outline/light_mode/key.svg +3 -0
  93. munchboka_edutools/static/icons/outline/light_mode/magnifying.svg +3 -0
  94. munchboka_edutools/static/icons/outline/light_mode/pencil_square.svg +3 -0
  95. munchboka_edutools/static/icons/outline/light_mode/play.svg +3 -0
  96. munchboka_edutools/static/icons/outline/light_mode/question.svg +3 -0
  97. munchboka_edutools/static/icons/outline/light_mode/square_check.svg +1 -0
  98. munchboka_edutools/static/icons/outline/light_mode/stop.svg +3 -0
  99. munchboka_edutools/static/icons/outline/light_mode/summary.svg +3 -0
  100. munchboka_edutools/static/icons/outline/light_mode/undo.svg +3 -0
  101. munchboka_edutools/static/icons/outline/light_mode/unlock.svg +3 -0
  102. munchboka_edutools/static/icons/polyicons/cubicdown.svg +3 -0
  103. munchboka_edutools/static/icons/polyicons/cubicup.svg +3 -0
  104. munchboka_edutools/static/icons/polyicons/frown.svg +3 -0
  105. munchboka_edutools/static/icons/polyicons/smile.svg +3 -0
  106. munchboka_edutools/static/icons/solid/dark_mode/academic.svg +5 -0
  107. munchboka_edutools/static/icons/solid/dark_mode/backward.svg +3 -0
  108. munchboka_edutools/static/icons/solid/dark_mode/book.svg +3 -0
  109. munchboka_edutools/static/icons/solid/dark_mode/brain.svg +1 -0
  110. munchboka_edutools/static/icons/solid/dark_mode/file.svg +1 -0
  111. munchboka_edutools/static/icons/solid/dark_mode/fire.svg +3 -0
  112. munchboka_edutools/static/icons/solid/dark_mode/key.svg +3 -0
  113. munchboka_edutools/static/icons/solid/dark_mode/pencil_square.svg +4 -0
  114. munchboka_edutools/static/icons/solid/dark_mode/play.svg +3 -0
  115. munchboka_edutools/static/icons/solid/dark_mode/python.svg +1 -0
  116. munchboka_edutools/static/icons/solid/dark_mode/scroll.svg +1 -0
  117. munchboka_edutools/static/icons/solid/dark_mode/stop.svg +3 -0
  118. munchboka_edutools/static/icons/solid/light_mode/academic.svg +5 -0
  119. munchboka_edutools/static/icons/solid/light_mode/backward.svg +3 -0
  120. munchboka_edutools/static/icons/solid/light_mode/book.svg +3 -0
  121. munchboka_edutools/static/icons/solid/light_mode/brain.svg +1 -0
  122. munchboka_edutools/static/icons/solid/light_mode/file.svg +1 -0
  123. munchboka_edutools/static/icons/solid/light_mode/fire.svg +3 -0
  124. munchboka_edutools/static/icons/solid/light_mode/key.svg +3 -0
  125. munchboka_edutools/static/icons/solid/light_mode/pencil_square.svg +4 -0
  126. munchboka_edutools/static/icons/solid/light_mode/play.svg +3 -0
  127. munchboka_edutools/static/icons/solid/light_mode/python.svg +1 -0
  128. munchboka_edutools/static/icons/solid/light_mode/scroll.svg +1 -0
  129. munchboka_edutools/static/icons/solid/light_mode/stop.svg +3 -0
  130. munchboka_edutools/static/icons/stickers/edit.svg +1 -0
  131. munchboka_edutools/static/icons/stickers/pencil_square.svg +3 -0
  132. munchboka_edutools/static/js/casThemeManager.js +99 -0
  133. munchboka_edutools/static/js/escapeRoom/escape-room.js +219 -0
  134. munchboka_edutools/static/js/flashcards.js +199 -0
  135. munchboka_edutools/static/js/geogebra-setup.js +6 -0
  136. munchboka_edutools/static/js/highlight-init.js +6 -0
  137. munchboka_edutools/static/js/interactiveCode/codeEditor.js +648 -0
  138. munchboka_edutools/static/js/interactiveCode/interactiveCodeSetup.js +441 -0
  139. munchboka_edutools/static/js/interactiveCode/pythonRunner.js +336 -0
  140. munchboka_edutools/static/js/interactiveCode/turtleCode.js +203 -0
  141. munchboka_edutools/static/js/interactiveCode/workerManager.js +353 -0
  142. munchboka_edutools/static/js/jeopardy.js +560 -0
  143. munchboka_edutools/static/js/pairPuzzle/draggableItem.js +64 -0
  144. munchboka_edutools/static/js/pairPuzzle/dropZone.js +119 -0
  145. munchboka_edutools/static/js/pairPuzzle/game.js +160 -0
  146. munchboka_edutools/static/js/parsons/parsonsPuzzle.js +641 -0
  147. munchboka_edutools/static/js/popup.js +85 -0
  148. munchboka_edutools/static/js/quiz.js +566 -0
  149. munchboka_edutools/static/js/skulpt/skulpt.js +35721 -0
  150. munchboka_edutools/static/js/timedQuiz/multipleChoiceQuestion.js +184 -0
  151. munchboka_edutools/static/js/timedQuiz/timedMultipleChoiceQuiz.js +244 -0
  152. munchboka_edutools/static/js/timedQuiz/utils.js +6 -0
  153. munchboka_edutools/static/js/utils.js +3 -0
  154. munchboka_edutools-0.2.3.dist-info/METADATA +109 -0
  155. munchboka_edutools-0.2.3.dist-info/RECORD +157 -0
  156. munchboka_edutools-0.2.3.dist-info/WHEEL +4 -0
  157. munchboka_edutools-0.2.3.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,441 @@
1
+ class InteractiveCodeSetup {
2
+ constructor(containerId, initialCode, preloadPackages = null) {
3
+ this.containerId = containerId;
4
+ this.initialCode = initialCode;
5
+ this.preloadPackages = preloadPackages;
6
+ console.log("InteractiveCodeSetup - Preload packages:", this.preloadPackages);
7
+ this.uniqueId = this.generateUUID();
8
+ console.log("Unique ID:", this.uniqueId);
9
+
10
+ // HTML element IDs
11
+ this.editorId = `code-editor-${this.uniqueId}`;
12
+ this.runButtonId = `run-button-${this.uniqueId}`;
13
+ this.resetButtonId = `reset-button-${this.uniqueId}`;
14
+ this.cancelButtonId = `cancel-button-${this.uniqueId}`;
15
+ this.outputId = `output-${this.uniqueId}`;
16
+ this.errorBoxId = `error-box-${this.uniqueId}`;
17
+
18
+ // Store instances of CodeEditor and PythonRunner
19
+ this.editorInstance = null;
20
+ this.runnerInstance = null;
21
+
22
+
23
+ // Initialize the editor setup
24
+ this.createEditorHTML();
25
+ this.setupInteractiveEditor();
26
+ }
27
+
28
+ generateUUID() {
29
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
30
+ const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
31
+ return v.toString(16);
32
+ });
33
+ }
34
+
35
+ createEditorHTML() {
36
+ const container = document.getElementById(this.containerId);
37
+ if (!container) {
38
+ console.error(`Container with ID ${this.containerId} not found.`);
39
+ return;
40
+ }
41
+
42
+ const runIcon = `
43
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
44
+ <path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z" />
45
+ </svg>
46
+ `;
47
+ const resetIcon = `
48
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-6">
49
+ <path fill-rule="evenodd" d="M9.53 2.47a.75.75 0 0 1 0 1.06L4.81 8.25H15a6.75 6.75 0 0 1 0 13.5h-3a.75.75 0 0 1 0-1.5h3a5.25 5.25 0 1 0 0-10.5H4.81l4.72 4.72a.75.75 0 1 1-1.06 1.06l-6-6a.75.75 0 0 1 0-1.06l6-6a.75.75 0 0 1 1.06 0Z" clip-rule="evenodd" />
50
+ </svg>
51
+ `;
52
+
53
+ const cancelIcon = `
54
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
55
+ <path stroke-linecap="round" stroke-linejoin="round" d="M5.25 7.5A2.25 2.25 0 0 1 7.5 5.25h9a2.25 2.25 0 0 1 2.25 2.25v9a2.25 2.25 0 0 1-2.25 2.25h-9a2.25 2.25 0 0 1-2.25-2.25v-9Z" />
56
+ </svg>
57
+ `;
58
+
59
+ const html = `
60
+ <div>
61
+ <textarea id="${this.editorId}" name="code-${this.uniqueId}">${this.initialCode}</textarea>
62
+
63
+ <button id="${this.runButtonId}" class="button button-run">Kjør kode ${runIcon}</button>
64
+ <button id="${this.resetButtonId}" class="button button-reset">Reset kode ${resetIcon}</button>
65
+ <button id="${this.cancelButtonId}" class="button button-cancel">Avbryt kjøring ${cancelIcon}</button>
66
+ </div>
67
+ <div id="${this.errorBoxId}"></div>
68
+ <pre id="${this.outputId}" class="pythonoutput"></pre>
69
+ `;
70
+
71
+ container.innerHTML = html;
72
+ }
73
+
74
+ setupInteractiveEditor() {
75
+ this.editorInstance = new CodeEditor(this.editorId); // Initialize the CodeEditor
76
+ this.runnerInstance = new PythonRunner(this.outputId, this.errorBoxId, this.preloadPackages); // Initialize the PythonRunner
77
+
78
+ // Add event listeners for buttons
79
+ document.getElementById(this.runButtonId).addEventListener("click", () => this.runCode());
80
+ document.getElementById(this.resetButtonId).addEventListener("click", () => this.resetCode());
81
+ document.getElementById(this.cancelButtonId).addEventListener("click", () => this.cancelCodeExecution());
82
+
83
+ // Set up localStorage persistence
84
+ this.setupLocalStoragePersistence();
85
+ }
86
+
87
+ setupLocalStoragePersistence() {
88
+ const storageKey = `interactive-code-${this.containerId}`;
89
+
90
+ // Restore saved code if available
91
+ const restoreState = () => {
92
+ if (this.editorInstance && this.editorInstance.editor) {
93
+ try {
94
+ const savedCode = localStorage.getItem(storageKey);
95
+ if (savedCode && savedCode !== this.initialCode) {
96
+ this.editorInstance.editor.setValue(savedCode);
97
+ }
98
+ // Update timestamp
99
+ localStorage.setItem(storageKey + '-timestamp', Date.now().toString());
100
+ } catch (e) {
101
+ // Silently fail if restore fails
102
+ }
103
+ } else {
104
+ // Retry if editor not ready
105
+ setTimeout(restoreState, 100);
106
+ }
107
+ };
108
+
109
+ // Start restoration
110
+ setTimeout(restoreState, 100);
111
+
112
+ // Save code when page unloads
113
+ window.addEventListener('beforeunload', () => {
114
+ this.saveState(storageKey);
115
+ });
116
+
117
+ // Also save when editor content changes (debounced)
118
+ let saveTimeout = null;
119
+ if (this.editorInstance && this.editorInstance.editor) {
120
+ this.editorInstance.editor.on('change', () => {
121
+ clearTimeout(saveTimeout);
122
+ saveTimeout = setTimeout(() => {
123
+ this.saveState(storageKey);
124
+ }, 1000); // Save 1 second after user stops typing
125
+ });
126
+ }
127
+ }
128
+
129
+ saveState(storageKey) {
130
+ if (!this.editorInstance || !this.editorInstance.editor) return;
131
+ try {
132
+ const code = this.editorInstance.getValue();
133
+ localStorage.setItem(storageKey, code);
134
+ localStorage.setItem(storageKey + '-timestamp', Date.now().toString());
135
+ } catch (e) {
136
+ // If quota exceeded, try cleanup and retry
137
+ if (e.name === 'QuotaExceededError') {
138
+ this.cleanupOldStates();
139
+ try {
140
+ const code = this.editorInstance.getValue();
141
+ localStorage.setItem(storageKey, code);
142
+ localStorage.setItem(storageKey + '-timestamp', Date.now().toString());
143
+ } catch (retryError) {
144
+ // Still failed - silently give up
145
+ }
146
+ }
147
+ }
148
+ }
149
+
150
+ cleanupOldStates() {
151
+ try {
152
+ // Find all interactive code states with timestamps
153
+ const codeStates = [];
154
+ for (let i = 0; i < localStorage.length; i++) {
155
+ const key = localStorage.key(i);
156
+ if (key && key.startsWith('interactive-code-') && key.endsWith('-timestamp')) {
157
+ const stateKey = key.replace('-timestamp', '');
158
+ const timestamp = parseInt(localStorage.getItem(key) || '0', 10);
159
+ codeStates.push({ key: stateKey, timestamp: timestamp });
160
+ }
161
+ }
162
+
163
+ // Sort by timestamp (oldest first)
164
+ codeStates.sort((a, b) => a.timestamp - b.timestamp);
165
+
166
+ // Delete oldest 25% of states (minimum 1, maximum 10)
167
+ const numToDelete = Math.max(1, Math.min(10, Math.floor(codeStates.length * 0.25)));
168
+ for (let i = 0; i < numToDelete && i < codeStates.length; i++) {
169
+ localStorage.removeItem(codeStates[i].key);
170
+ localStorage.removeItem(codeStates[i].key + '-timestamp');
171
+ }
172
+ } catch (e) {
173
+ // Cleanup failed - silently continue
174
+ }
175
+ }
176
+
177
+
178
+
179
+ runCode() {
180
+ this.clearOutput();
181
+ this.runnerInstance.run(this.editorInstance); // Pass the editor instance to PythonRunner for execution
182
+ }
183
+
184
+ resetCode() {
185
+ this.clearOutput();
186
+ this.editorInstance.resetEditor(this.initialCode); // Reset the editor content to the initial code
187
+ }
188
+
189
+ cancelCodeExecution() {
190
+ if (this.runnerInstance.workerManager) {
191
+ this.runnerInstance.workerManager.restartWorker(); // Restart the worker to cancel code execution
192
+ }
193
+ }
194
+
195
+ clearOutput() {
196
+ document.getElementById(this.outputId).textContent = "";
197
+ document.getElementById(this.errorBoxId).textContent = "";
198
+ }
199
+ }
200
+
201
+
202
+ function makeInteractiveCode(containerId, initialCode, preloadPackages = null) {
203
+ return new InteractiveCodeSetup(containerId, initialCode, preloadPackages);
204
+ }
205
+
206
+
207
+ // predictionInteractiveCodeSetup.js
208
+
209
+ class PredictionInteractiveCodeSetup extends InteractiveCodeSetup {
210
+ constructor(containerId, initialCode) {
211
+ super(containerId, initialCode);
212
+
213
+ // Additional IDs for the prediction feature
214
+ this.predictionInputId = `prediction-input-${this.uniqueId}`;
215
+ this.lockPredictionButtonId = `lock-prediction-button-${this.uniqueId}`;
216
+ this.predictionDisplayId = `prediction-display-${this.uniqueId}`;
217
+ this.predictionOutputId = `prediction-output-${this.uniqueId}`;
218
+ this.predictionOutputContainerId = `prediction-output-container-${this.uniqueId}`;
219
+ this.predictionContainerId = `prediction-container-${this.uniqueId}`;
220
+ // this.initialCode = initialCode;
221
+
222
+ // Flag to track whether the prediction has been displayed
223
+ this.predictionDisplayed = false;
224
+
225
+ // Modify the HTML to include prediction elements
226
+ this.addPredictionHTML();
227
+
228
+ // Set up the prediction feature
229
+ this.setupPredictionFeature();
230
+ }
231
+
232
+ addPredictionHTML() {
233
+ const container = document.getElementById(this.containerId);
234
+ if (!container) {
235
+ console.error(`Container with ID ${this.containerId} not found.`);
236
+ return;
237
+ }
238
+
239
+ // Build the prediction input HTML
240
+ const predictionHtml = `
241
+ <div id="${this.predictionContainerId}" class="prediction-container">
242
+ <textarea id="${this.predictionInputId}" rows="3" placeholder="Skriv inn svaret ditt her! \n \nTrykk på Enter (&#9166;) for en ny linje."></textarea>
243
+ <button id="${this.lockPredictionButtonId}" class="button button-run">Sjekk svaret!</button>
244
+ </div>
245
+ `;
246
+
247
+ // Insert the prediction input after the existing editor HTML
248
+ container.insertAdjacentHTML('beforeend', predictionHtml);
249
+
250
+ // Create the prediction-output container
251
+ const predictionOutputContainer = document.createElement('div');
252
+ predictionOutputContainer.id = this.predictionOutputContainerId;
253
+ predictionOutputContainer.className = 'prediction-output-container';
254
+ predictionOutputContainer.style.display = 'none';
255
+
256
+ // Create the prediction display
257
+ const predictionDisplay = document.createElement('div');
258
+ predictionDisplay.className = 'prediction-display';
259
+ predictionDisplay.innerHTML = `
260
+ <h3>Ditt svar:</h3>
261
+ <pre id="${this.predictionDisplayId}"></pre>
262
+ `;
263
+
264
+ // Create the output display for prediction phase
265
+ const outputDisplay = document.createElement('div');
266
+ outputDisplay.className = 'output-display';
267
+ outputDisplay.innerHTML = `
268
+ <h3>Faktisk utskrift:</h3>
269
+ <pre id="${this.predictionOutputId}" class="pythonoutput"></pre>
270
+ `;
271
+
272
+ // Append the displays to the prediction-output container
273
+ predictionOutputContainer.appendChild(predictionDisplay);
274
+ predictionOutputContainer.appendChild(outputDisplay);
275
+
276
+ // Append the prediction-output container after the error box
277
+ const errorBoxElement = document.getElementById(this.errorBoxId);
278
+ if (errorBoxElement) {
279
+ errorBoxElement.insertAdjacentElement('afterend', predictionOutputContainer);
280
+ } else {
281
+ console.error(`Error box element with ID ${this.errorBoxId} not found.`);
282
+ container.appendChild(predictionOutputContainer);
283
+ }
284
+
285
+ // Save a reference to the original output element
286
+ this.originalOutputElement = document.getElementById(this.outputId);
287
+ }
288
+
289
+
290
+
291
+ setupPredictionFeature() {
292
+ // Make the code editor read-only initially
293
+ // Use setTimeout to ensure the editor is fully initialized
294
+ const setupReadOnly = () => {
295
+ // Check if editor instance exists and has been properly initialized
296
+ if (this.editorInstance && this.editorInstance.editor) {
297
+ console.log("Setting editor to read-only");
298
+ this.editorInstance.editor.setOption('readOnly', true);
299
+
300
+ // Hide the buttons now that we know the editor is ready
301
+ document.getElementById(this.runButtonId).style.display = 'none';
302
+ document.getElementById(this.resetButtonId).style.display = 'none';
303
+ document.getElementById(this.cancelButtonId).style.display = 'none';
304
+ } else {
305
+ console.log("Editor not ready yet, retrying in 100ms...");
306
+ // Retry after a short delay
307
+ setTimeout(setupReadOnly, 100);
308
+ }
309
+ };
310
+
311
+ // Start the setup process
312
+ setupReadOnly();
313
+
314
+
315
+ // this.editorInstance.editor.setOption('readOnly', true);
316
+
317
+ // // Hide the run/reset/cancel buttons until the prediction is made
318
+ // document.getElementById(this.runButtonId).style.display = 'none';
319
+ // document.getElementById(this.resetButtonId).style.display = 'none';
320
+ // document.getElementById(this.cancelButtonId).style.display = 'none';
321
+
322
+ // Add event listener for the lock prediction button
323
+ document.getElementById(this.lockPredictionButtonId).addEventListener("click", () => this.lockPrediction());
324
+ }
325
+
326
+ lockPrediction() {
327
+ const prediction = document.getElementById(this.predictionInputId).value;
328
+
329
+ // Store the prediction
330
+ this.prediction = prediction;
331
+
332
+ // Hide the prediction input area
333
+ const predictionContainer = document.getElementById(this.predictionContainerId);
334
+ if (predictionContainer) {
335
+ predictionContainer.style.display = 'none';
336
+ }
337
+
338
+ // Make the code editor editable
339
+ this.editorInstance.editor.setOption('readOnly', false);
340
+
341
+ // Show the run/reset/cancel buttons
342
+ document.getElementById(this.runButtonId).style.display = 'inline-block';
343
+ document.getElementById(this.resetButtonId).style.display = 'inline-block';
344
+ document.getElementById(this.cancelButtonId).style.display = 'inline-block';
345
+
346
+ // Automatically run the code
347
+ this.runCode();
348
+ }
349
+
350
+ runCode() {
351
+ if (this.predictionDisplayed) {
352
+ // Replace with a new InteractiveCodeSetup instance
353
+ this.initialCode = this.editorInstance.getValue();
354
+ this.replaceWithInteractiveCodeSetup();
355
+
356
+ } else {
357
+ // First run after prediction is locked in
358
+ this.clearOutput();
359
+ this.runnerInstance.run(this.editorInstance, this.predictionOutputId); // Pass the new output ID
360
+
361
+ // Display the prediction and output side by side
362
+ this.displayPredictionAndOutput();
363
+
364
+ // Set flag to indicate prediction has been displayed
365
+ this.predictionDisplayed = true;
366
+ }
367
+ }
368
+
369
+ resetCode() {
370
+ if (this.predictionDisplayed) {
371
+ // Replace with a new InteractiveCodeSetup instance
372
+ this.replaceWithInteractiveCodeSetup();
373
+ } else {
374
+ // First reset (unlikely, but handle just in case)
375
+ this.clearOutput();
376
+ this.editorInstance.resetEditor(this.initialCode);
377
+ }
378
+ }
379
+
380
+ cancelCodeExecution() {
381
+ if (this.predictionDisplayed) {
382
+ // Replace with a new InteractiveCodeSetup instance
383
+ this.replaceWithInteractiveCodeSetup();
384
+ } else {
385
+ // First cancel after prediction is locked in
386
+ if (this.runnerInstance.workerManager) {
387
+ this.runnerInstance.workerManager.restartWorker();
388
+ }
389
+ }
390
+ }
391
+
392
+ replaceWithInteractiveCodeSetup() {
393
+ // Get the container element
394
+ const container = document.getElementById(this.containerId);
395
+ if (container) {
396
+ // Clear the container's content
397
+ container.innerHTML = '';
398
+
399
+ // Create a new instance of InteractiveCodeSetup
400
+ new InteractiveCodeSetup(this.containerId, this.initialCode);
401
+ } else {
402
+ console.error(`Container with ID ${this.containerId} not found.`);
403
+ }
404
+ }
405
+
406
+ displayPredictionAndOutput() {
407
+ // Display the user's prediction
408
+ document.getElementById(this.predictionDisplayId).textContent = this.prediction;
409
+
410
+ // Hide the original output element
411
+ if (this.originalOutputElement) {
412
+ this.originalOutputElement.style.display = 'none';
413
+ }
414
+
415
+ // Show the prediction-output container
416
+ document.getElementById(this.predictionOutputContainerId).style.display = 'flex';
417
+ }
418
+
419
+ clearOutput() {
420
+ if (this.predictionDisplayed) {
421
+ const outputElement = document.getElementById(this.predictionOutputId);
422
+ if (outputElement) {
423
+ outputElement.textContent = "";
424
+ }
425
+ } else {
426
+ const outputElement = document.getElementById(this.outputId);
427
+ if (outputElement) {
428
+ outputElement.textContent = "";
429
+ }
430
+ }
431
+ const errorBoxElement = document.getElementById(this.errorBoxId);
432
+ if (errorBoxElement) {
433
+ errorBoxElement.textContent = "";
434
+ }
435
+ }
436
+ }
437
+
438
+ // Function to initialize the prediction code editor
439
+ function makePredictionInteractiveCode(containerId, initialCode) {
440
+ return new PredictionInteractiveCodeSetup(containerId, initialCode);
441
+ }