munchboka-edutools 0.1.13__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 (149) 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 +272 -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/factor_tree.py +549 -0
  11. munchboka_edutools/directives/ggb.py +209 -0
  12. munchboka_edutools/directives/ggb_icon.py +105 -0
  13. munchboka_edutools/directives/ggb_popup.py +165 -0
  14. munchboka_edutools/directives/horner.py +324 -0
  15. munchboka_edutools/directives/interactive_code.py +75 -0
  16. munchboka_edutools/directives/jeopardy.py +252 -0
  17. munchboka_edutools/directives/multi_plot.py +1126 -0
  18. munchboka_edutools/directives/pair_puzzle.py +191 -0
  19. munchboka_edutools/directives/parsons.py +109 -0
  20. munchboka_edutools/directives/plot.py +3105 -0
  21. munchboka_edutools/directives/poly_icon.py +111 -0
  22. munchboka_edutools/directives/polydiv.py +344 -0
  23. munchboka_edutools/directives/popup.py +245 -0
  24. munchboka_edutools/directives/quiz.py +291 -0
  25. munchboka_edutools/directives/signchart.py +516 -0
  26. munchboka_edutools/directives/timed_quiz.py +436 -0
  27. munchboka_edutools/directives/turtle.py +157 -0
  28. munchboka_edutools/static/css/admonitions.css +2012 -0
  29. munchboka_edutools/static/css/cas_popup.css +242 -0
  30. munchboka_edutools/static/css/code_mirror_themes/github_dark_cm.css +112 -0
  31. munchboka_edutools/static/css/code_mirror_themes/github_dark_default_cm.css +40 -0
  32. munchboka_edutools/static/css/code_mirror_themes/github_dark_high_contrast_cm.css +141 -0
  33. munchboka_edutools/static/css/code_mirror_themes/github_light_cm.css +120 -0
  34. munchboka_edutools/static/css/code_mirror_themes/github_light_default_cm.css +108 -0
  35. munchboka_edutools/static/css/code_mirror_themes/one_dark_cm.css +121 -0
  36. munchboka_edutools/static/css/dialogue.css +92 -0
  37. munchboka_edutools/static/css/escapeRoom/escape-room.css +223 -0
  38. munchboka_edutools/static/css/figures.css +274 -0
  39. munchboka_edutools/static/css/general_style.css +74 -0
  40. munchboka_edutools/static/css/github-dark-high-contrast.css +141 -0
  41. munchboka_edutools/static/css/github-dark.css +112 -0
  42. munchboka_edutools/static/css/github-light.css +120 -0
  43. munchboka_edutools/static/css/interactive_code/style.css +575 -0
  44. munchboka_edutools/static/css/interactive_code.css +582 -0
  45. munchboka_edutools/static/css/jeopardy.css +529 -0
  46. munchboka_edutools/static/css/pairPuzzle/style.css +177 -0
  47. munchboka_edutools/static/css/parsons/parsonsPuzzle.css +331 -0
  48. munchboka_edutools/static/css/popup.css +115 -0
  49. munchboka_edutools/static/css/quiz.css +312 -0
  50. munchboka_edutools/static/css/timedQuiz.css +375 -0
  51. munchboka_edutools/static/icons/ggb/mode_evaluate.svg +1 -0
  52. munchboka_edutools/static/icons/ggb/mode_extremum.svg +1 -0
  53. munchboka_edutools/static/icons/ggb/mode_intersect.svg +1 -0
  54. munchboka_edutools/static/icons/ggb/mode_nsolve.svg +1 -0
  55. munchboka_edutools/static/icons/ggb/mode_numeric.svg +1 -0
  56. munchboka_edutools/static/icons/ggb/mode_point.svg +1 -0
  57. munchboka_edutools/static/icons/ggb/mode_solve.svg +1 -0
  58. munchboka_edutools/static/icons/misc/windows-logo.svg +1 -0
  59. munchboka_edutools/static/icons/outline/dark_mode/academic.svg +3 -0
  60. munchboka_edutools/static/icons/outline/dark_mode/backward.svg +3 -0
  61. munchboka_edutools/static/icons/outline/dark_mode/book.svg +3 -0
  62. munchboka_edutools/static/icons/outline/dark_mode/chat_bubble.svg +3 -0
  63. munchboka_edutools/static/icons/outline/dark_mode/check.svg +3 -0
  64. munchboka_edutools/static/icons/outline/dark_mode/cmd_line.svg +3 -0
  65. munchboka_edutools/static/icons/outline/dark_mode/file.svg +1 -0
  66. munchboka_edutools/static/icons/outline/dark_mode/fire.svg +4 -0
  67. munchboka_edutools/static/icons/outline/dark_mode/key.svg +3 -0
  68. munchboka_edutools/static/icons/outline/dark_mode/magnifying.svg +3 -0
  69. munchboka_edutools/static/icons/outline/dark_mode/pencil_square.svg +3 -0
  70. munchboka_edutools/static/icons/outline/dark_mode/play.svg +3 -0
  71. munchboka_edutools/static/icons/outline/dark_mode/question.svg +3 -0
  72. munchboka_edutools/static/icons/outline/dark_mode/square_check.svg +1 -0
  73. munchboka_edutools/static/icons/outline/dark_mode/stop.svg +3 -0
  74. munchboka_edutools/static/icons/outline/dark_mode/summary.svg +3 -0
  75. munchboka_edutools/static/icons/outline/dark_mode/undo.svg +3 -0
  76. munchboka_edutools/static/icons/outline/dark_mode/unlock.svg +3 -0
  77. munchboka_edutools/static/icons/outline/light_mode/academic.svg +3 -0
  78. munchboka_edutools/static/icons/outline/light_mode/backward.svg +3 -0
  79. munchboka_edutools/static/icons/outline/light_mode/book.svg +3 -0
  80. munchboka_edutools/static/icons/outline/light_mode/chat_bubble.svg +3 -0
  81. munchboka_edutools/static/icons/outline/light_mode/check.svg +3 -0
  82. munchboka_edutools/static/icons/outline/light_mode/cmd_line.svg +3 -0
  83. munchboka_edutools/static/icons/outline/light_mode/file.svg +1 -0
  84. munchboka_edutools/static/icons/outline/light_mode/fire.svg +4 -0
  85. munchboka_edutools/static/icons/outline/light_mode/key.svg +3 -0
  86. munchboka_edutools/static/icons/outline/light_mode/magnifying.svg +3 -0
  87. munchboka_edutools/static/icons/outline/light_mode/pencil_square.svg +3 -0
  88. munchboka_edutools/static/icons/outline/light_mode/play.svg +3 -0
  89. munchboka_edutools/static/icons/outline/light_mode/question.svg +3 -0
  90. munchboka_edutools/static/icons/outline/light_mode/square_check.svg +1 -0
  91. munchboka_edutools/static/icons/outline/light_mode/stop.svg +3 -0
  92. munchboka_edutools/static/icons/outline/light_mode/summary.svg +3 -0
  93. munchboka_edutools/static/icons/outline/light_mode/undo.svg +3 -0
  94. munchboka_edutools/static/icons/outline/light_mode/unlock.svg +3 -0
  95. munchboka_edutools/static/icons/polyicons/cubicdown.svg +3 -0
  96. munchboka_edutools/static/icons/polyicons/cubicup.svg +3 -0
  97. munchboka_edutools/static/icons/polyicons/frown.svg +3 -0
  98. munchboka_edutools/static/icons/polyicons/smile.svg +3 -0
  99. munchboka_edutools/static/icons/solid/dark_mode/academic.svg +5 -0
  100. munchboka_edutools/static/icons/solid/dark_mode/backward.svg +3 -0
  101. munchboka_edutools/static/icons/solid/dark_mode/book.svg +3 -0
  102. munchboka_edutools/static/icons/solid/dark_mode/brain.svg +1 -0
  103. munchboka_edutools/static/icons/solid/dark_mode/file.svg +1 -0
  104. munchboka_edutools/static/icons/solid/dark_mode/fire.svg +3 -0
  105. munchboka_edutools/static/icons/solid/dark_mode/key.svg +3 -0
  106. munchboka_edutools/static/icons/solid/dark_mode/pencil_square.svg +4 -0
  107. munchboka_edutools/static/icons/solid/dark_mode/play.svg +3 -0
  108. munchboka_edutools/static/icons/solid/dark_mode/python.svg +1 -0
  109. munchboka_edutools/static/icons/solid/dark_mode/scroll.svg +1 -0
  110. munchboka_edutools/static/icons/solid/dark_mode/stop.svg +3 -0
  111. munchboka_edutools/static/icons/solid/light_mode/academic.svg +5 -0
  112. munchboka_edutools/static/icons/solid/light_mode/backward.svg +3 -0
  113. munchboka_edutools/static/icons/solid/light_mode/book.svg +3 -0
  114. munchboka_edutools/static/icons/solid/light_mode/brain.svg +1 -0
  115. munchboka_edutools/static/icons/solid/light_mode/file.svg +1 -0
  116. munchboka_edutools/static/icons/solid/light_mode/fire.svg +3 -0
  117. munchboka_edutools/static/icons/solid/light_mode/key.svg +3 -0
  118. munchboka_edutools/static/icons/solid/light_mode/pencil_square.svg +4 -0
  119. munchboka_edutools/static/icons/solid/light_mode/play.svg +3 -0
  120. munchboka_edutools/static/icons/solid/light_mode/python.svg +1 -0
  121. munchboka_edutools/static/icons/solid/light_mode/scroll.svg +1 -0
  122. munchboka_edutools/static/icons/solid/light_mode/stop.svg +3 -0
  123. munchboka_edutools/static/icons/stickers/edit.svg +1 -0
  124. munchboka_edutools/static/icons/stickers/pencil_square.svg +3 -0
  125. munchboka_edutools/static/js/casThemeManager.js +99 -0
  126. munchboka_edutools/static/js/escapeRoom/escape-room.js +219 -0
  127. munchboka_edutools/static/js/geogebra-setup.js +6 -0
  128. munchboka_edutools/static/js/highlight-init.js +6 -0
  129. munchboka_edutools/static/js/interactiveCode/codeEditor.js +632 -0
  130. munchboka_edutools/static/js/interactiveCode/interactiveCodeSetup.js +348 -0
  131. munchboka_edutools/static/js/interactiveCode/pythonRunner.js +336 -0
  132. munchboka_edutools/static/js/interactiveCode/turtleCode.js +203 -0
  133. munchboka_edutools/static/js/interactiveCode/workerManager.js +353 -0
  134. munchboka_edutools/static/js/jeopardy.js +523 -0
  135. munchboka_edutools/static/js/pairPuzzle/draggableItem.js +64 -0
  136. munchboka_edutools/static/js/pairPuzzle/dropZone.js +119 -0
  137. munchboka_edutools/static/js/pairPuzzle/game.js +160 -0
  138. munchboka_edutools/static/js/parsons/parsonsPuzzle.js +641 -0
  139. munchboka_edutools/static/js/popup.js +85 -0
  140. munchboka_edutools/static/js/quiz.js +422 -0
  141. munchboka_edutools/static/js/skulpt/skulpt.js +35721 -0
  142. munchboka_edutools/static/js/timedQuiz/multipleChoiceQuestion.js +184 -0
  143. munchboka_edutools/static/js/timedQuiz/timedMultipleChoiceQuiz.js +244 -0
  144. munchboka_edutools/static/js/timedQuiz/utils.js +6 -0
  145. munchboka_edutools/static/js/utils.js +3 -0
  146. munchboka_edutools-0.1.13.dist-info/METADATA +108 -0
  147. munchboka_edutools-0.1.13.dist-info/RECORD +149 -0
  148. munchboka_edutools-0.1.13.dist-info/WHEEL +4 -0
  149. munchboka_edutools-0.1.13.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,219 @@
1
+ (function(){
2
+ function renderMathIfAvailable(root){
3
+ if (typeof renderMathInElement === 'function') {
4
+ try { renderMathInElement(root, {delimiters: [
5
+ {left: '$$', right: '$$', display: true},
6
+ {left: '$', right: '$', display: false},
7
+ {left: '\\(', right: '\\)', display: false},
8
+ {left: '\\[', right: '\\]', display: true}
9
+ ]}); } catch(e){}
10
+ }
11
+ }
12
+
13
+ function highlightCodeIfAvailable(root){
14
+ if (typeof hljs !== 'undefined' && root) {
15
+ try {
16
+ root.querySelectorAll('pre code').forEach(function(block){
17
+ hljs.highlightElement(block);
18
+ });
19
+ } catch(e){}
20
+ }
21
+ }
22
+
23
+ function initEscapeRoom(container){
24
+ let cfg = null;
25
+ try {
26
+ // Prefer inline JSON script to avoid attribute escaping issues
27
+ const dataNode = container.querySelector('script.escape-room-data[type="application/json"]');
28
+ let raw = dataNode ? (dataNode.textContent || dataNode.innerText || '') : '';
29
+ if (!raw || !raw.trim()) {
30
+ raw = container.getAttribute('data-config') || '{}';
31
+ }
32
+ // Fallback: decode HTML entities if present in attribute form
33
+ if (raw && raw.indexOf('&') !== -1 && raw.indexOf('{') === -1) {
34
+ const ta = document.createElement('textarea'); ta.innerHTML = raw; raw = ta.value;
35
+ }
36
+ cfg = JSON.parse(raw);
37
+ } catch(e){ cfg = {}; }
38
+ const steps = Array.isArray(cfg.steps) ? cfg.steps : [];
39
+ const storageKey = 'escapeRoom:' + (container && container.id ? container.id : 'default');
40
+
41
+ function loadProgress(){
42
+ try {
43
+ const raw = window.localStorage.getItem(storageKey);
44
+ if (!raw) return null;
45
+ const obj = JSON.parse(raw);
46
+ if (obj && typeof obj.idx === 'number') {
47
+ // Clamp index to available steps
48
+ const clamped = Math.max(0, Math.min(steps.length, Math.floor(obj.idx)));
49
+ return { idx: clamped };
50
+ }
51
+ } catch(e){}
52
+ return null;
53
+ }
54
+ function saveProgress(i){
55
+ try { window.localStorage.setItem(storageKey, JSON.stringify({ idx: i })); } catch(e){}
56
+ }
57
+ function clearProgress(){
58
+ try { window.localStorage.removeItem(storageKey); } catch(e){}
59
+ }
60
+ const caseInsensitive = !!cfg.caseInsensitive;
61
+
62
+ // Build UI
63
+ const root = document.createElement('div');
64
+ root.className = 'er-root';
65
+
66
+ const header = document.createElement('div');
67
+ header.className = 'er-header';
68
+ const progress = document.createElement('div');
69
+ progress.className = 'er-progress';
70
+ header.appendChild(progress);
71
+ // Visual progress bar under the label
72
+ const progressBar = document.createElement('div');
73
+ progressBar.className = 'er-progressbar';
74
+ progressBar.setAttribute('role', 'progressbar');
75
+ progressBar.setAttribute('aria-valuemin', '0');
76
+ progressBar.setAttribute('aria-valuemax', String((Array.isArray(cfg.steps)?cfg.steps:[]).length||0));
77
+ const progressFill = document.createElement('div');
78
+ progressFill.className = 'er-progressbar-fill';
79
+ progressBar.appendChild(progressFill);
80
+ header.appendChild(progressBar);
81
+
82
+ const body = document.createElement('div');
83
+ body.className = 'er-body';
84
+
85
+ const controls = document.createElement('div');
86
+ controls.className = 'er-controls';
87
+ const codeInput = document.createElement('input'); codeInput.type = 'text'; codeInput.placeholder = 'Skriv kode';
88
+ const submitBtn = document.createElement('button'); submitBtn.className='er-btn primary'; submitBtn.textContent='Sjekk';
89
+ const feedback = document.createElement('div'); feedback.className='er-feedback';
90
+ controls.appendChild(codeInput); controls.appendChild(submitBtn);
91
+
92
+ root.appendChild(header); root.appendChild(body); root.appendChild(controls); root.appendChild(feedback);
93
+
94
+ let idx = 0;
95
+ let resumePromptShown = false;
96
+ // Avoid auto-scrolling on initial load by not auto-focusing until user interacts
97
+ let userInitiated = false;
98
+ const markUserInitiated = ()=>{ userInitiated = true; try { codeInput.focus({ preventScroll: true }); } catch(e){ try { codeInput.focus(); } catch(_){} } };
99
+ try {
100
+ container.addEventListener('pointerdown', markUserInitiated, { once: true, capture: true });
101
+ container.addEventListener('keydown', function onKey(){ userInitiated = true; container.removeEventListener('keydown', onKey, true); }, true);
102
+ } catch(e){}
103
+
104
+ function normalizeCode(s){
105
+ const t = String(s||'').trim();
106
+ return caseInsensitive ? t.toLowerCase() : t;
107
+ }
108
+
109
+ function updateProgress(){
110
+ progress.textContent = `Rom ${Math.min(idx+1, steps.length)} av ${steps.length}`;
111
+ const total = steps.length || 1;
112
+ const completed = Math.min(idx, steps.length);
113
+ const pct = Math.max(0, Math.min(100, Math.round((completed/total)*100)));
114
+ try { progressFill.style.width = pct + '%'; } catch(e){}
115
+ try {
116
+ progressBar.setAttribute('aria-valuenow', String(completed));
117
+ progressBar.setAttribute('aria-valuemax', String(total));
118
+ } catch(e){}
119
+ root.appendChild(header); root.appendChild(body); root.appendChild(controls); root.appendChild(feedback);
120
+ }
121
+
122
+ function renderStep(){
123
+ body.innerHTML = '';
124
+ feedback.textContent = '';
125
+ updateProgress();
126
+ if (idx >= steps.length){
127
+ const done = document.createElement('div');
128
+ done.className = 'er-complete';
129
+ done.innerHTML = '<h3> Ferdig! 🎉</h3>';
130
+ body.appendChild(done);
131
+ controls.style.display = 'none';
132
+ // Clear saved progress on completion
133
+ clearProgress();
134
+ return;
135
+ }
136
+ controls.style.display = '';
137
+ const step = steps[idx] || {};
138
+ const title = document.createElement('h3'); title.className='er-title'; title.textContent = step.title || `Oppgave ${idx+1}`;
139
+ const q = document.createElement('div'); q.className='er-q'; q.innerHTML = step.question || '';
140
+ body.appendChild(title); body.appendChild(q);
141
+ renderMathIfAvailable(q); highlightCodeIfAvailable(q);
142
+ codeInput.value = '';
143
+ if (userInitiated) {
144
+ try { codeInput.focus({ preventScroll: true }); } catch(e){ try { codeInput.focus(); } catch(_){} }
145
+ }
146
+ }
147
+
148
+ function showResumePrompt(savedIndex){
149
+ resumePromptShown = true;
150
+ // Hide normal UI until choice made
151
+ body.innerHTML = '';
152
+ controls.style.display = 'none';
153
+ feedback.textContent = '';
154
+ const p = document.createElement('div');
155
+ p.className = 'er-resume-prompt';
156
+ const txt = document.createElement('div');
157
+ txt.className = 'er-resume-text';
158
+ const roomNum = Math.min((savedIndex||0)+1, steps.length);
159
+ txt.textContent = `Fortsett der du slapp (rom ${roomNum} av ${steps.length})?`;
160
+ const actions = document.createElement('div');
161
+ actions.className = 'er-resume-actions';
162
+ const btnStart = document.createElement('button'); btnStart.className='er-btn accent'; btnStart.textContent='Start fra begynnelsen';
163
+ const btnResume = document.createElement('button'); btnResume.className='er-btn primary'; btnResume.textContent='Fortsett';
164
+ actions.appendChild(btnStart); actions.appendChild(btnResume);
165
+ p.appendChild(txt); p.appendChild(actions);
166
+ body.appendChild(p);
167
+ btnStart.addEventListener('click', ()=>{
168
+ idx = 0;
169
+ clearProgress();
170
+ controls.style.display = '';
171
+ renderStep();
172
+ });
173
+ btnResume.addEventListener('click', ()=>{
174
+ idx = Math.max(0, Math.min(steps.length, savedIndex||0));
175
+ controls.style.display = '';
176
+ renderStep();
177
+ });
178
+ }
179
+
180
+ function check(){
181
+ const step = steps[idx] || {};
182
+ const allowed = Array.isArray(step.codes) ? step.codes : [];
183
+ const entered = normalizeCode(codeInput.value);
184
+ const ok = allowed.map(normalizeCode).includes(entered);
185
+ if (ok){
186
+ feedback.textContent = '';
187
+ idx += 1;
188
+ // Persist progress after each successful room
189
+ saveProgress(idx);
190
+ renderStep();
191
+ } else {
192
+ feedback.textContent = 'Feil kode. Prøv igjen.';
193
+ feedback.classList.add('er-error');
194
+ setTimeout(()=>{ feedback.classList.remove('er-error'); }, 500);
195
+ }
196
+ }
197
+
198
+ submitBtn.addEventListener('click', check);
199
+ codeInput.addEventListener('keydown', function(e){
200
+ if (e.key === 'Enter') { e.preventDefault(); check(); }
201
+ });
202
+
203
+ container.innerHTML = '';
204
+ container.appendChild(root);
205
+ // Optional resume: only show prompt if saved progress exists and is within bounds
206
+ const saved = loadProgress();
207
+ if (saved && typeof saved.idx === 'number' && saved.idx > 0 && saved.idx <= steps.length) {
208
+ showResumePrompt(saved.idx);
209
+ } else {
210
+ // Ensure no stale progress
211
+ if (saved && (saved.idx <= 0 || saved.idx > steps.length)) clearProgress();
212
+ renderStep();
213
+ }
214
+ }
215
+
216
+ document.addEventListener('DOMContentLoaded', function(){
217
+ document.querySelectorAll('.escape-room-container').forEach(initEscapeRoom);
218
+ });
219
+ })();
@@ -0,0 +1,6 @@
1
+ function setupGeogebra(containerId, options) {
2
+ options.id = containerId + '-applet'; // Ensure unique ID for each applet
3
+
4
+ var applet = new GGBApplet(options, true); // 'true' for using HTML5
5
+ applet.inject(containerId); // This injects the applet into the container
6
+ }
@@ -0,0 +1,6 @@
1
+ // Initialize highlight.js for syntax highlighting
2
+ document.addEventListener('DOMContentLoaded', function() {
3
+ if (typeof hljs !== 'undefined') {
4
+ hljs.highlightAll();
5
+ }
6
+ });