diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f3147a6..d77cb9a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is loosely inspired by Keep a Changelog. ### Changed +- **Web 0.14.34, broken lesson steps repaired:** lesson 3 step „Ausprobieren“ ended with „probiere Folgendes aus:“ and no list, and the checklist sat in the same step without its own heading; now there are four things to try (title, save in the workspace, open again in a second tab, export PNG and PDF), the step comes before the game, and „Checkliste“ is its own step (de/en/pt). VisuBot lesson „Sensoren“ step „Was liefert der Sensor?“ had no text; it now explains that a sensor gives a value, that a comparison turns it into `true` or `false` (table with three conditions), the comparison operators and `==` vs. `=` (de/en). The cloze explanation in lesson 4 pointed to a lesson „Java“; it is called „Struktogramm und Code“ (de/en/pt). New tests: the checklist stands in its own step „Checkliste“, and no text ends with a colon with nothing after it. - **Web 0.14.33, a game in every lesson:** every lesson now has at least one game before its checklist (Holger: Kompetenzen, game, checklist, quiz in every lesson). New: VisuStruct lesson 36 „Zahlenraten“ gets „Zu klein oder zu groß?“ (hints, smart guessing by halving, `Math.random` ranges, guess counter, `setEnabled`, 1 to 1000; de/en/pt). All 26 robot lessons without a game get one (de/en), using the existing game types: question rounds („Welcher Baustein?“, „Wie oft fährt er?“, „Welcher Datentyp?“, „Spiel den Computer“, „Befehl oder Sensor?“, „Kopf oder Fuß?“, „Linie oder nicht?“, „Wahr oder falsch?“, „Welcher Fall läuft?“, „Notbremse“, „Licht an oder aus?“, „Laut oder leise?“, „Zu schief?“, „Welche Farbe?“, „Welche LED leuchtet?“, „Welches Fach?“, „Was steht auf dem Bildschirm?“, „Wohin fährt er?“, „Stoppuhr und Akku“, „Welche Methode?“), „Bombe entschärfen“ with mBot2 code (L6 distance, L8 colours, L19 strings) and „Von tief nach hoch“ (order, L16 speaker). Robot lessons now end like the VisuStruct lessons with the steps game, „Checkliste“ and „Wissenstest“ (the last quiz moves from the last content step to its own step after the checklist; L2 and L22 keep their quizzes in place). Because steps were inserted, saved self-assessments and quiz answers in these lessons start fresh. Tests check that every lesson in both worlds has a game before the checklist. Ten robot lessons get a second „Bombe entschärfen“ round with mBot2 code (L3, L8, L10, L11, L15, L19, L20, L22, L23, L27). New game type `::: spiel fahrt` „Wo landet der mBot2?“ (`web/src/learn/driveGame.ts`, `web/src/ui/driveGameView.ts`): each round shows mBot2 code and a small map with walls, black and coloured fields; the pupil taps the field where the robot stops, then the robot drives the route on the map using the real simulation (L1, L3, L4, L7, L8, L10; a test drives every round and checks the target field). New game type `::: spiel kreuzwort` „Begriffe-Rätsel“: a standalone crossword with the terms of the lesson and a keyword (L5, L18, L24, L27, one per VisuBot part; de ROBOTER, SENSOR, AKTOR, METHODE, en ROBOT, SENSOR, SOUND, METHOD). - **Web 0.14.32, VisuBot: missing basics added:** four new robot lessons, inserted by file name without renaming (the series now has 27 lessons): „Struktogramm und Editor“ at the start (algorithm, Nassi-Shneiderman, the three building blocks with mBot2 examples, inserting/moving/deleting, saving and the workspace; exercise „Um die Ecke“), „Schritt für Schritt testen“ after Variables (simulation controls, desk-check table, logic error exercise „Die Spirale reparieren“ with a faulty start diagram), „Erst fahren, dann prüfen“ after the while loop (do-while vs. while table, structogram exercise, Java „Schritte zählen“) and „Notbremse mit break“ after buttons/joystick (endless loop with exit, Java `while (true)` + `break` with button A). Every robot lesson from lesson 4 on now has a Java exercise „Warum läuft das nicht?“ (`vb-fehler-`): Ludwig's version of the lesson's program has one mistake (wrong case, typo, missing argument, unknown variable, missing quotation marks); the student runs it, reads the error message and fixes it. Lesson 22 gets the Java exercise „Rechteck mit Umdrehungen“. A test checks that every start diagram fails its exercise (de/en). - **Web 0.14.31, web app links point to visucode.de:** the website now lives on one subdomain per world (visustruct.visucode.de, visubot.visucode.de, visuobject.visucode.de, published from the GitLab repo visucode/website). The app's home, imprint and privacy links go to the start page of the current world there (relative on its own subdomain, e.g. `../de/index.html`, otherwise absolute); before, in VisuBot they pointed to `../de/visubot.html`, which no longer exists. On visubot.visucode.de and visuobject.visucode.de the app starts in that world when no world was chosen yet. The about link (web and Swift app) and the Messprotokoll links in lesson 22 use the new addresses (`web/src/ui/site.ts`, test `site.test.ts`). diff --git a/web/lessons/de/03-speichern-oeffnen-exportieren.md b/web/lessons/de/03-speichern-oeffnen-exportieren.md index dcd03bbf..a7e15afe 100644 --- a/web/lessons/de/03-speichern-oeffnen-exportieren.md +++ b/web/lessons/de/03-speichern-oeffnen-exportieren.md @@ -83,6 +83,17 @@ Den [Titel](#zeige-titel) eines Diagramms trägst du in das Feld über dem Struk Unter dem [Zahnrad](#zeige-textgroesse) oben rechts stellst du bei Textgröße die Schriftgröße ein. Ein größerer Text wirkt auch beim Exportieren als Bild. +## Ausprobieren + +Öffne eine deiner Übungen aus Lektion 2 und probiere Folgendes aus: + +1. Gib dem Diagramm im Feld [Titel](#zeige-titel) über dem Struktogramm einen Namen, zum Beispiel `Hallo Welt`. +2. [Speichere](#zeige-speichern) es in deinem Workspace. Schau in der Spalte [📁 Dateien](#zeige-dateien) nach: Steht es im Ordner von heute? +3. Öffne mit **+** einen zweiten Reiter und klicke dort in der Spalte Dateien auf dein Programm. Es öffnet sich wieder. +4. [Exportiere](#zeige-exportieren) es als **Bild (PNG)** und als **PDF (A4)**. Öffne beide Dateien und vergleiche sie. + +Klappt alles? Dann weißt du, wo deine Programme liegen, und kannst sie weitergeben. + ## Spiel: Wie gibst du es weiter? ::: spiel frage @@ -122,9 +133,7 @@ richtig: PNG > Ein PNG kann jeder sofort ansehen, ohne VisuStruct. ::: -## Ausprobieren - -Öffne eine deiner Übungen aus Lektion 2 und probiere Folgendes aus: +## Checkliste Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀️ kann ich sicher. Bei ⛅ und ☂️ hilft dir **Nachlesen**. Danach kommt der Wissenstest. Er zeigt dir, ob deine Einschätzung stimmt. diff --git a/web/lessons/de/04-variablen-und-datentypen.md b/web/lessons/de/04-variablen-und-datentypen.md index 79ebfd5d..de291a3b 100644 --- a/web/lessons/de/04-variablen-und-datentypen.md +++ b/web/lessons/de/04-variablen-und-datentypen.md @@ -254,7 +254,7 @@ auftrag: Ergänze die fehlenden Wörter. Ganz außen steht der Rahmen, den jedes } } ``` -erklärung: Ganze Zahlen sind `int`, Kommazahlen `double`, Texte `String` (groß geschrieben) und Wahrheitswerte `boolean`. `public class` und `public static void main` bilden den Rahmen. Im Bereich Code darfst du ihn weglassen, mehr dazu in der Lektion „Java“. +erklärung: Ganze Zahlen sind `int`, Kommazahlen `double`, Texte `String` (groß geschrieben) und Wahrheitswerte `boolean`. `public class` und `public static void main` bilden den Rahmen. Im Bereich Code darfst du ihn weglassen, mehr dazu in der Lektion „Struktogramm und Code“. ::: ## Fehler finden: Sekunden diff --git a/web/lessons/de/visubot/04-sensoren.md b/web/lessons/de/visubot/04-sensoren.md index 80fb47bc..38583465 100644 --- a/web/lessons/de/visubot/04-sensoren.md +++ b/web/lessons/de/visubot/04-sensoren.md @@ -53,6 +53,18 @@ lösung: vb-wand-vorn-loesung.visustruct ## Was liefert der Sensor? +Ein Sensor liefert einen **Wert**, so wie eine Variable. Fährt der mBot2 weiter, ändert sich der Wert: Der Abstand wird kleiner, je näher die Wand kommt. Erst ein **Vergleich** macht aus dem Wert eine Frage mit der Antwort `true` (wahr) oder `false` (falsch). + +| Bedingung | Frage | Antwort bei 38 cm Abstand | +|---|---|---| +| `mbot.getDistance() < 20` | Ist die Wand näher als 20 cm? | `false` | +| `mbot.getDistance() > 30` | Ist mehr als 30 cm Platz? | `true` | +| `mbot.getLine() == 0` | Ist unter dem mBot2 alles hell? | hängt vom Boden ab | + +Vergleichen kannst du mit `<` (kleiner), `>` (größer), `<=` (kleiner oder gleich), `>=` (größer oder gleich), `==` (gleich) und `!=` (ungleich). + +> Für „gleich“ schreibst du **zwei** Gleichheitszeichen: `==`. Ein einzelnes `=` legt einen Wert in eine Variable, das ist etwas ganz anderes. + > 📘 **Mehr dazu ohne Roboter:** In VisuStruct gibt es die Lektion [„Verzweigung“](?visustruct&lektion=08-verzweigung). Sie öffnet sich in einem neuen Fenster. ::: übung vb-fehler-04-sensoren diff --git a/web/lessons/en/03-speichern-oeffnen-exportieren.md b/web/lessons/en/03-speichern-oeffnen-exportieren.md index 4a2b018a..a4710e76 100644 --- a/web/lessons/en/03-speichern-oeffnen-exportieren.md +++ b/web/lessons/en/03-speichern-oeffnen-exportieren.md @@ -83,6 +83,17 @@ With [Export](#zeige-exportieren) in the tools (icon with an arrow pointing up) Under the [gear](#zeige-textgroesse) at the top right, Text size sets the font size. Larger text also shows when you export an image. +## Try it out + +Open one of your exercises from lesson 2 and try the following: + +1. Give the diagram a name in the [title](#zeige-titel) field above the structure chart, for example `Hello World`. +2. [Save](#zeige-speichern) it in your workspace. Look in the [📁 Files](#zeige-dateien) column: is it in today's folder? +3. Open a second tab with **+** and click your program in the Files column there. It opens again. +4. [Export](#zeige-exportieren) it as an **image (PNG)** and as a **PDF (A4)**. Open both files and compare them. + +Did everything work? Then you know where your programs are and how to share them. + ## Game: How do you pass it on? ::: spiel frage @@ -122,9 +133,7 @@ richtig: PNG > Anyone can look at a PNG straight away, without VisuStruct. ::: -## Try it out - -Open one of your exercises from lesson 2 and try the following: +## Checklist Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can do this confidently. For ⛅ and ☂️, **Review** helps you. Then comes the quiz. It shows you whether your self-assessment is right. diff --git a/web/lessons/en/04-variablen-und-datentypen.md b/web/lessons/en/04-variablen-und-datentypen.md index 58d9e1f2..bb81269e 100644 --- a/web/lessons/en/04-variablen-und-datentypen.md +++ b/web/lessons/en/04-variablen-und-datentypen.md @@ -254,7 +254,7 @@ auftrag: Fill in the missing words. On the outside is the frame that every Java } } ``` -erklärung: Whole numbers are `int`, decimal numbers `double`, texts `String` (with a capital S) and truth values `boolean`. `public class` and `public static void main` make up the frame. In the Code area you may leave it out, more on this in the lesson “Java”. +erklärung: Whole numbers are `int`, decimal numbers `double`, texts `String` (with a capital S) and truth values `boolean`. `public class` and `public static void main` make up the frame. In the Code area you may leave it out, more on this in the lesson “Structure chart and code”. ::: ## Find the bug: seconds diff --git a/web/lessons/en/visubot/04-sensoren.md b/web/lessons/en/visubot/04-sensoren.md index 659bfad7..40e01b43 100644 --- a/web/lessons/en/visubot/04-sensoren.md +++ b/web/lessons/en/visubot/04-sensoren.md @@ -53,6 +53,18 @@ lösung: vb-wand-vorn-loesung.visustruct ## What does the sensor give you? +A sensor gives you a **value**, just like a variable. When the mBot2 drives on, the value changes: the distance gets smaller as the wall comes closer. Only a **comparison** turns the value into a question with the answer `true` or `false`. + +| Condition | Question | Answer at a distance of 38 cm | +|---|---|---| +| `mbot.getDistance() < 20` | Is the wall closer than 20 cm? | `false` | +| `mbot.getDistance() > 30` | Is there more than 30 cm of space? | `true` | +| `mbot.getLine() == 0` | Is everything bright under the mBot2? | depends on the floor | + +You can compare with `<` (less than), `>` (greater than), `<=` (less than or equal), `>=` (greater than or equal), `==` (equal) and `!=` (not equal). + +> For "equal" you write **two** equals signs: `==`. A single `=` puts a value into a variable, which is something completely different. + > 📘 **More without the robot:** VisuStruct has the lesson ["Branch"](?visustruct&lektion=08-verzweigung). It opens in a new window. ::: übung vb-fehler-04-sensoren diff --git a/web/lessons/pt/03-speichern-oeffnen-exportieren.md b/web/lessons/pt/03-speichern-oeffnen-exportieren.md index ee53aa68..c3fcd62c 100644 --- a/web/lessons/pt/03-speichern-oeffnen-exportieren.md +++ b/web/lessons/pt/03-speichern-oeffnen-exportieren.md @@ -83,6 +83,17 @@ Com [Exportar](#zeige-exportieren) nas ferramentas (ícone com uma seta para cim Na [roda dentada](#zeige-textgroesse) em cima à direita, em Tamanho do texto, defines o tamanho da letra. O texto maior também se nota quando exportas uma imagem. +## Experimenta + +Abre um dos teus exercícios da lição 2 e experimenta o seguinte: + +1. Dá um nome ao diagrama no campo [título](#zeige-titel) por cima do estrutograma, por exemplo `Olá Mundo`. +2. [Guarda-o](#zeige-speichern) no teu espaço de trabalho. Vê na coluna [📁 Ficheiros](#zeige-dateien): está na pasta de hoje? +3. Abre um segundo separador com **+** e clica lá no teu programa na coluna Ficheiros. Volta a abrir-se. +4. [Exporta-o](#zeige-exportieren) como **imagem (PNG)** e como **PDF (A4)**. Abre os dois ficheiros e compara-os. + +Correu tudo bem? Então sabes onde estão os teus programas e como os partilhar. + ## Jogo: Como o partilhas? ::: spiel frage @@ -122,9 +133,7 @@ richtig: PNG > Um PNG pode ser visto logo por qualquer pessoa, sem VisuStruct. ::: -## Experimenta - -Abre um dos teus exercícios da lição 2 e experimenta o seguinte: +## Lista de verificação Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ consigo com segurança. Com ⛅ e ☂️, **Rever** ajuda-te. Depois vem o teste de conhecimentos. Mostra-te se a tua autoavaliação está certa. diff --git a/web/lessons/pt/04-variablen-und-datentypen.md b/web/lessons/pt/04-variablen-und-datentypen.md index 4ca15c6b..9c97cc0e 100644 --- a/web/lessons/pt/04-variablen-und-datentypen.md +++ b/web/lessons/pt/04-variablen-und-datentypen.md @@ -254,7 +254,7 @@ auftrag: Preenche as palavras que faltam. Por fora está a moldura de que qualqu } } ``` -erklärung: Números inteiros são `int`, números decimais `double`, textos `String` (com S maiúsculo) e valores lógicos `boolean`. `public class` e `public static void main` formam a moldura. Na área Código podes deixá-la de fora, há mais sobre isto na lição “Java”. +erklärung: Números inteiros são `int`, números decimais `double`, textos `String` (com S maiúsculo) e valores lógicos `boolean`. `public class` e `public static void main` formam a moldura. Na área Código podes deixá-la de fora, há mais sobre isto na lição “Estrutograma e código”. ::: ## Encontra o erro: segundos diff --git a/web/package-lock.json b/web/package-lock.json index 865c406c..252d98b8 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,12 +1,12 @@ { "name": "visustruct-web", - "version": "0.14.33", + "version": "0.14.34", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "visustruct-web", - "version": "0.14.31", + "version": "0.14.34", "dependencies": { "@codemirror/autocomplete": "^6.20.4", "@codemirror/commands": "^6.11.1", diff --git a/web/package.json b/web/package.json index 250a187e..d0d1876c 100644 --- a/web/package.json +++ b/web/package.json @@ -1,7 +1,7 @@ { "name": "visustruct-web", "private": true, - "version": "0.14.33", + "version": "0.14.34", "type": "module", "scripts": { "dev": "vite", diff --git a/web/test/lessons.test.ts b/web/test/lessons.test.ts index 526065e9..f6af38a0 100644 --- a/web/test/lessons.test.ts +++ b/web/test/lessons.test.ts @@ -42,6 +42,34 @@ describe.each(contentLanguages)('Lernbereich: Inhalte (%s)', (lang) => { } }) + it('die Checkliste steht in einem eigenen Schritt „Checkliste“', () => { + const title = { de: 'Checkliste', en: 'Checklist', pt: 'Lista de verificação' }[lang] + for (const lesson of lessons) { + const step = lesson.steps.find((s) => s.blocks.some((b) => b.kind === 'checklist')) + expect(step?.title, lesson.id).toBe(title) + } + }) + + it('kein Text endet mit einem Doppelpunkt, ohne dass etwas folgt', () => { + // „probiere Folgendes aus:“ ohne Liste darunter (Lektion 3 hatte das) + const problems: string[] = [] + for (const lesson of lessons) { + for (const step of lesson.steps) { + step.blocks.forEach((block, i) => { + if (block.kind !== 'markdown') return + const parts = block.text.trim().split(/\n\s*\n/).map((p) => p.trim()) + const next = step.blocks[i + 1] + parts.forEach((part, k) => { + if (!part.endsWith(':') || part.includes('\n')) return + const follows = k + 1 < parts.length || (next && next.kind !== 'markdown' && next.kind !== 'checklist') + if (!follows) problems.push(`${lesson.id} / ${step.title}: ${part}`) + }) + }) + } + } + expect(problems).toEqual([]) + }) + it('jedes verwendete Diagramm existiert und lässt sich laden', () => { for (const { where, block } of allBlocks()) { const files = diff --git a/website/app/assets/flowApp-C8yZ_A03.js b/website/app/assets/flowApp-D9O9LuF5.js similarity index 99% rename from website/app/assets/flowApp-C8yZ_A03.js rename to website/app/assets/flowApp-D9O9LuF5.js index eac8c75f..02b4daa7 100644 --- a/website/app/assets/flowApp-C8yZ_A03.js +++ b/website/app/assets/flowApp-D9O9LuF5.js @@ -1,4 +1,4 @@ -var dt=Object.defineProperty;var lt=(i,t,e)=>t in i?dt(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var y=(i,t,e)=>lt(i,typeof t!="symbol"?t+"":t,e);import{t as h,g as ct,i as I,w as ht,o as ut,f as ft,q as G,u as pt,v as gt,x as wt,y as vt,z as mt,l as xt,n as yt}from"./index-BJMBJyRW.js";const et=["start","anweisung","ein","verzweigung","unterprogramm","ende"],m=20,st={start:"#d1f2d9",ende:"#d1f2d9",anweisung:"#e5f0ff",ein:"#f2e6ff",verzweigung:"#fff4d6",unterprogramm:"#e5f0ff"},H=16,bt=170;function _t(i,t,e){const n=[];for(const s of i.split(` +var dt=Object.defineProperty;var lt=(i,t,e)=>t in i?dt(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var y=(i,t,e)=>lt(i,typeof t!="symbol"?t+"":t,e);import{t as h,g as ct,i as I,w as ht,o as ut,f as ft,q as G,u as pt,v as gt,x as wt,y as vt,z as mt,l as xt,n as yt}from"./index-xN_dxLEc.js";const et=["start","anweisung","ein","verzweigung","unterprogramm","ende"],m=20,st={start:"#d1f2d9",ende:"#d1f2d9",anweisung:"#e5f0ff",ein:"#f2e6ff",verzweigung:"#fff4d6",unterprogramm:"#e5f0ff"},H=16,bt=170;function _t(i,t,e){const n=[];for(const s of i.split(` `)){let o="";for(const r of s.split(/\s+/).filter(Boolean)){const a=o?`${o} ${r}`:r;o&&e(a)>t?(n.push(o),o=r):o=a}n.push(o)}return n.length?n:[""]}const U=i=>Math.round(i/m)*m;function C(i,t){const e=_t(i.text,bt,t),n=Math.max(0,...e.map(t)),s=e.length*H;let o,r;if(i.shape==="verzweigung")o=Math.max(140,n*1.7+30),r=Math.max(80,s*1.8+24);else{const a=i.shape==="ein"?44:i.shape==="unterprogramm"?40:i.shape==="anweisung"?24:36;o=Math.max(i.shape==="start"||i.shape==="ende"?100:120,n+a),r=Math.max(40,s+18)}return{x:i.x,y:i.y,w:Math.ceil(o/m)*m,h:Math.ceil(r/m)*m,lines:e}}function V(i){return i==="ende"?[]:i==="verzweigung"?["ja","nein"]:["out"]}const P=i=>i!=="start";function j(i,t,e){var s;if(e==="out")return"bottom";const n=((s=i.yesRight)==null?void 0:s.includes(t.id))??!1;return e==="ja"===n?"right":"bottom"}function F(i,t){return t==="bottom"?[i.x,i.y+i.h/2]:[i.x+i.w/2,i.y]}const $t=i=>[i.x,i.y-i.h/2];function Lt(i,t,e,n=0){const[s,o]=F(i,t),[r,a]=$t(e),d=m,u=Math.max(i.x+i.w/2,e.x+e.w/2)+d*(1.5+n);if(t==="bottom"){if(a>=o+d){if(s===r)return[[s,o],[r,a]];const l=o+d;return[[s,o],[s,l],[r,l],[r,a]]}return[[s,o],[s,o+d],[u,o+d],[u,a-d],[r,a-d],[r,a]]}const p=e.x-e.w/2;if(p>=s+d&&Math.abs(e.y-o)=o+d){if(r>=s+d)return[[s,o],[r,o],[r,a]];const l=s+d;return[[s,o],[l,o],[l,a-d],[r,a-d],[r,a]]}const f=Math.max(s+d,u);return[[s,o],[f,o],[f,a-d],[r,a-d],[r,a]]}function nt(i=""){return{title:i,nodes:[],edges:[]}}function it(i,t){const e=new Set([...i.nodes.map(s=>s.id),...i.edges.map(s=>s.id)]);let n=1;for(;e.has(`${t}${n}`);)n++;return`${t}${n}`}function q(i,t,e,n,s){const o=it(i,"n");return{doc:{...i,nodes:[...i.nodes,{id:o,shape:t,x:U(e),y:U(n),text:s}]},id:o}}function J(i,t,e,n){return{...i,nodes:i.nodes.map(s=>s.id===t?{...s,x:Math.max(m*4,U(e)),y:Math.max(m*2,U(n))}:s)}}function Et(i,t,e){return{...i,nodes:i.nodes.map(n=>n.id===t?{...n,text:e}:n)}}function _(i,t,e,n){const s=i.nodes.find(a=>a.id===t),o=i.nodes.find(a=>a.id===n);if(!s||!o||t===n||!V(s.shape).includes(e)||!P(o.shape))return i;const r=i.edges.filter(a=>!(a.from===t&&a.port===e));return{...i,edges:[...r,{id:it(i,"e"),from:t,port:e,to:n}]}}function kt(i,t){return V(t.shape).find(e=>!i.edges.some(n=>n.from===t.id&&n.port===e))}function St(i,t){var e;return{...i,nodes:i.nodes.filter(n=>n.id!==t),edges:i.edges.filter(n=>n.from!==t&&n.to!==t),yesRight:(e=i.yesRight)==null?void 0:e.filter(n=>n!==t)}}function Mt(i,t){return{...i,edges:i.edges.filter(e=>e.id!==t)}}function ot(i,t){const e=new Set(i.yesRight??[]);return e.has(t)?e.delete(t):e.add(t),{...i,yesRight:[...e]}}function b(i){return JSON.stringify({format:"visuflow",version:1,...i},null,2)}function W(i){let t;try{t=JSON.parse(i)}catch{return}if(!t||typeof t!="object")return;const e=t;if(!Array.isArray(e.nodes)||!Array.isArray(e.edges))return;const n=[];for(const o of e.nodes)!o||typeof o.id!="string"||!et.includes(o.shape)||!Number.isFinite(o.x)||!Number.isFinite(o.y)||n.some(r=>r.id===o.id)||n.push({id:o.id,shape:o.shape,x:o.x,y:o.y,text:typeof o.text=="string"?o.text:""});let s={title:typeof e.title=="string"?e.title:"",nodes:n,edges:[]};for(const o of e.edges)!o||typeof o.from!="string"||typeof o.to!="string"||typeof o.port!="string"||(s=_(s,o.from,o.port,o.to));return Array.isArray(e.yesRight)&&(s.yesRight=e.yesRight.filter(o=>typeof o=="string"&&n.some(r=>r.id===o))),s}const z="http://www.w3.org/2000/svg",X="visuflow.doc",At=100,Y=14,rt=`${Y}px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif`,B="#1c1c1e",w=i=>i.replace(/[&<>"]/g,t=>({"&":"&","<":"<",">":">",'"':"""})[t]);function It(i){try{return localStorage.getItem(i)}catch{return null}}function Z(i,t){try{localStorage.setItem(i,t)}catch{}}function Ct(){return xt("visustruct",yt())}function D(i,t,e){const n=URL.createObjectURL(new Blob([t],{type:e})),s=document.createElement("a");s.href=n,s.download=i,s.click(),setTimeout(()=>URL.revokeObjectURL(n),1e3)}function v(i,t={}){const e=document.createElementNS(z,i);for(const[n,s]of Object.entries(t))e.setAttribute(n,String(s));return e}let N;function R(i){return N===void 0&&(N=document.createElement("canvas").getContext("2d")),N?(N.font=rt,N.measureText(i).width):i.length*Y*.55}const Rt=i=>h(`web_visuflow_shape_${i}`),T=i=>h(`web_visuflow_text_${i}`);function at(i,t){const e=t.x-t.w/2,n=t.x+t.w/2,s=t.y-t.h/2,o=t.y+t.h/2;return i==="verzweigung"?v("path",{d:`M${t.x} ${s} L${n} ${t.y} L${t.x} ${o} L${e} ${t.y} Z`}):i==="ein"?v("path",{d:`M${e+14} ${s} L${n} ${s} L${n-14} ${o} L${e} ${o} Z`}):i==="unterprogramm"?v("path",{d:`M${e} ${s} H${n} V${o} H${e} Z M${e+10} ${s} V${o} M${n-10} ${s} V${o}`}):v("rect",{x:e,y:s,width:t.w,height:t.h,rx:i==="anweisung"?2:t.h/2})}function Bt(i){const t=v("text",{"text-anchor":"middle","font-size":Y,fill:B});return i.lines.forEach((e,n)=>{const s=v("tspan",{x:i.x,y:i.y+5+(n-(i.lines.length-1)/2)*H});s.textContent=e,t.append(s)}),t}function Q(i){const t=v("svg",{viewBox:"0 0 64 36",width:64,height:36,"aria-hidden":"true"}),e=at(i,{x:32,y:18,w:i==="verzweigung"?54:56,h:i==="verzweigung"?32:26});return e.setAttribute("fill",st[i]),e.setAttribute("stroke",B),e.setAttribute("stroke-width","1.5"),t.append(e),t.outerHTML}function tt(){let i=nt(h("web_visuflow_example_title"));const t=[],e=(p,f,l,c)=>{const g=q(i,p,f,l,c);i=g.doc,t.push(g.id)};e("start",240,60,T("start")),e("anweisung",240,160,h("web_visuflow_example_water")),e("anweisung",240,260,h("web_visuflow_example_bag")),e("verzweigung",240,380,h("web_visuflow_example_hot")),e("anweisung",480,380,h("web_visuflow_example_wait")),e("anweisung",240,500,h("web_visuflow_example_drink")),e("ende",240,600,T("ende"));const[n,s,o,r,a,d,u]=t;return i=_(i,n,"out",s),i=_(i,s,"out",o),i=_(i,o,"out",r),i=ot(i,r),i=_(i,r,"ja",a),i=_(i,a,"out",r),i=_(i,r,"nein",d),i=_(i,d,"out",u),i}function Tt(){return q(nt(),"start",240,60,T("start")).doc}class Dt{constructor(t){y(this,"shell");y(this,"svg");y(this,"scroller");y(this,"status");y(this,"titleInput");y(this,"doc");y(this,"selection");y(this,"history",[]);y(this,"future",[]);y(this,"editor");y(this,"dragLine");document.documentElement.classList.add("visuflow-theme"),history.replaceState(history.state,"",`${location.pathname}?visuflow${location.hash}`),this.doc=W(It(X)??"")??tt(),this.shell=document.createElement("div"),this.shell.className="shell visuflow",t.replaceWith(this.shell),this.build(),this.render(),window.addEventListener("keydown",e=>this.onKey(e))}build(){const t=(l,c,g,x=c)=>``,e=et.map(l=>``).join("");this.shell.innerHTML=`
VisuFlow ${w(h("web_visuflow_subtitle"))} @@ -28,7 +28,7 @@ var dt=Object.defineProperty;var lt=(i,t,e)=>t in i?dt(i,t,{enumerable:!0,config ${ht()}
- ${w(h("web_about_version_fmt").replace("%@","0.14.33"))} + ${w(h("web_about_version_fmt").replace("%@","0.14.34"))}
diff --git a/website/app/assets/index-BJMBJyRW.js b/website/app/assets/index-xN_dxLEc.js similarity index 99% rename from website/app/assets/index-BJMBJyRW.js rename to website/app/assets/index-xN_dxLEc.js index bab6b119..4fbe73a1 100644 --- a/website/app/assets/index-BJMBJyRW.js +++ b/website/app/assets/index-xN_dxLEc.js @@ -967,6 +967,17 @@ Den [Titel](#zeige-titel) eines Diagramms trägst du in das Feld über dem Struk Unter dem [Zahnrad](#zeige-textgroesse) oben rechts stellst du bei Textgröße die Schriftgröße ein. Ein größerer Text wirkt auch beim Exportieren als Bild. +## Ausprobieren + +Öffne eine deiner Übungen aus Lektion 2 und probiere Folgendes aus: + +1. Gib dem Diagramm im Feld [Titel](#zeige-titel) über dem Struktogramm einen Namen, zum Beispiel \`Hallo Welt\`. +2. [Speichere](#zeige-speichern) es in deinem Workspace. Schau in der Spalte [📁 Dateien](#zeige-dateien) nach: Steht es im Ordner von heute? +3. Öffne mit **+** einen zweiten Reiter und klicke dort in der Spalte Dateien auf dein Programm. Es öffnet sich wieder. +4. [Exportiere](#zeige-exportieren) es als **Bild (PNG)** und als **PDF (A4)**. Öffne beide Dateien und vergleiche sie. + +Klappt alles? Dann weißt du, wo deine Programme liegen, und kannst sie weitergeben. + ## Spiel: Wie gibst du es weiter? ::: spiel frage @@ -1006,9 +1017,7 @@ richtig: PNG > Ein PNG kann jeder sofort ansehen, ohne VisuStruct. ::: -## Ausprobieren - -Öffne eine deiner Übungen aus Lektion 2 und probiere Folgendes aus: +## Checkliste Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀️ kann ich sicher. Bei ⛅ und ☂️ hilft dir **Nachlesen**. Danach kommt der Wissenstest. Er zeigt dir, ob deine Einschätzung stimmt. @@ -1300,7 +1309,7 @@ auftrag: Ergänze die fehlenden Wörter. Ganz außen steht der Rahmen, den jedes } } \`\`\` -erklärung: Ganze Zahlen sind \`int\`, Kommazahlen \`double\`, Texte \`String\` (groß geschrieben) und Wahrheitswerte \`boolean\`. \`public class\` und \`public static void main\` bilden den Rahmen. Im Bereich Code darfst du ihn weglassen, mehr dazu in der Lektion „Java“. +erklärung: Ganze Zahlen sind \`int\`, Kommazahlen \`double\`, Texte \`String\` (groß geschrieben) und Wahrheitswerte \`boolean\`. \`public class\` und \`public static void main\` bilden den Rahmen. Im Bereich Code darfst du ihn weglassen, mehr dazu in der Lektion „Struktogramm und Code“. ::: ## Fehler finden: Sekunden @@ -13633,6 +13642,17 @@ With [Export](#zeige-exportieren) in the tools (icon with an arrow pointing up) Under the [gear](#zeige-textgroesse) at the top right, Text size sets the font size. Larger text also shows when you export an image. +## Try it out + +Open one of your exercises from lesson 2 and try the following: + +1. Give the diagram a name in the [title](#zeige-titel) field above the structure chart, for example \`Hello World\`. +2. [Save](#zeige-speichern) it in your workspace. Look in the [📁 Files](#zeige-dateien) column: is it in today's folder? +3. Open a second tab with **+** and click your program in the Files column there. It opens again. +4. [Export](#zeige-exportieren) it as an **image (PNG)** and as a **PDF (A4)**. Open both files and compare them. + +Did everything work? Then you know where your programs are and how to share them. + ## Game: How do you pass it on? ::: spiel frage @@ -13672,9 +13692,7 @@ richtig: PNG > Anyone can look at a PNG straight away, without VisuStruct. ::: -## Try it out - -Open one of your exercises from lesson 2 and try the following: +## Checklist Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can do this confidently. For ⛅ and ☂️, **Review** helps you. Then comes the quiz. It shows you whether your self-assessment is right. @@ -13966,7 +13984,7 @@ auftrag: Fill in the missing words. On the outside is the frame that every Java } } \`\`\` -erklärung: Whole numbers are \`int\`, decimal numbers \`double\`, texts \`String\` (with a capital S) and truth values \`boolean\`. \`public class\` and \`public static void main\` make up the frame. In the Code area you may leave it out, more on this in the lesson “Java”. +erklärung: Whole numbers are \`int\`, decimal numbers \`double\`, texts \`String\` (with a capital S) and truth values \`boolean\`. \`public class\` and \`public static void main\` make up the frame. In the Code area you may leave it out, more on this in the lesson “Structure chart and code”. ::: ## Find the bug: seconds @@ -26304,6 +26322,17 @@ Com [Exportar](#zeige-exportieren) nas ferramentas (ícone com uma seta para cim Na [roda dentada](#zeige-textgroesse) em cima à direita, em Tamanho do texto, defines o tamanho da letra. O texto maior também se nota quando exportas uma imagem. +## Experimenta + +Abre um dos teus exercícios da lição 2 e experimenta o seguinte: + +1. Dá um nome ao diagrama no campo [título](#zeige-titel) por cima do estrutograma, por exemplo \`Olá Mundo\`. +2. [Guarda-o](#zeige-speichern) no teu espaço de trabalho. Vê na coluna [📁 Ficheiros](#zeige-dateien): está na pasta de hoje? +3. Abre um segundo separador com **+** e clica lá no teu programa na coluna Ficheiros. Volta a abrir-se. +4. [Exporta-o](#zeige-exportieren) como **imagem (PNG)** e como **PDF (A4)**. Abre os dois ficheiros e compara-os. + +Correu tudo bem? Então sabes onde estão os teus programas e como os partilhar. + ## Jogo: Como o partilhas? ::: spiel frage @@ -26343,9 +26372,7 @@ richtig: PNG > Um PNG pode ser visto logo por qualquer pessoa, sem VisuStruct. ::: -## Experimenta - -Abre um dos teus exercícios da lição 2 e experimenta o seguinte: +## Lista de verificação Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ consigo com segurança. Com ⛅ e ☂️, **Rever** ajuda-te. Depois vem o teste de conhecimentos. Mostra-te se a tua autoavaliação está certa. @@ -26637,7 +26664,7 @@ auftrag: Preenche as palavras que faltam. Por fora está a moldura de que qualqu } } \`\`\` -erklärung: Números inteiros são \`int\`, números decimais \`double\`, textos \`String\` (com S maiúsculo) e valores lógicos \`boolean\`. \`public class\` e \`public static void main\` formam a moldura. Na área Código podes deixá-la de fora, há mais sobre isto na lição “Java”. +erklärung: Números inteiros são \`int\`, números decimais \`double\`, textos \`String\` (com S maiúsculo) e valores lógicos \`boolean\`. \`public class\` e \`public static void main\` formam a moldura. Na área Código podes deixá-la de fora, há mais sobre isto na lição “Estrutograma e código”. ::: ## Encontra o erro: segundos @@ -42255,6 +42282,18 @@ lösung: vb-wand-vorn-loesung.visustruct ## Was liefert der Sensor? +Ein Sensor liefert einen **Wert**, so wie eine Variable. Fährt der mBot2 weiter, ändert sich der Wert: Der Abstand wird kleiner, je näher die Wand kommt. Erst ein **Vergleich** macht aus dem Wert eine Frage mit der Antwort \`true\` (wahr) oder \`false\` (falsch). + +| Bedingung | Frage | Antwort bei 38 cm Abstand | +|---|---|---| +| \`mbot.getDistance() < 20\` | Ist die Wand näher als 20 cm? | \`false\` | +| \`mbot.getDistance() > 30\` | Ist mehr als 30 cm Platz? | \`true\` | +| \`mbot.getLine() == 0\` | Ist unter dem mBot2 alles hell? | hängt vom Boden ab | + +Vergleichen kannst du mit \`<\` (kleiner), \`>\` (größer), \`<=\` (kleiner oder gleich), \`>=\` (größer oder gleich), \`==\` (gleich) und \`!=\` (ungleich). + +> Für „gleich“ schreibst du **zwei** Gleichheitszeichen: \`==\`. Ein einzelnes \`=\` legt einen Wert in eine Variable, das ist etwas ganz anderes. + > 📘 **Mehr dazu ohne Roboter:** In VisuStruct gibt es die Lektion [„Verzweigung“](?visustruct&lektion=08-verzweigung). Sie öffnet sich in einem neuen Fenster. ::: übung vb-fehler-04-sensoren @@ -48202,6 +48241,18 @@ lösung: vb-wand-vorn-loesung.visustruct ## What does the sensor give you? +A sensor gives you a **value**, just like a variable. When the mBot2 drives on, the value changes: the distance gets smaller as the wall comes closer. Only a **comparison** turns the value into a question with the answer \`true\` or \`false\`. + +| Condition | Question | Answer at a distance of 38 cm | +|---|---|---| +| \`mbot.getDistance() < 20\` | Is the wall closer than 20 cm? | \`false\` | +| \`mbot.getDistance() > 30\` | Is there more than 30 cm of space? | \`true\` | +| \`mbot.getLine() == 0\` | Is everything bright under the mBot2? | depends on the floor | + +You can compare with \`<\` (less than), \`>\` (greater than), \`<=\` (less than or equal), \`>=\` (greater than or equal), \`==\` (equal) and \`!=\` (not equal). + +> For "equal" you write **two** equals signs: \`==\`. A single \`=\` puts a value into a variable, which is something completely different. + > 📘 **More without the robot:** VisuStruct has the lesson ["Branch"](?visustruct&lektion=08-verzweigung). It opens in a new window. ::: übung vb-fehler-04-sensoren @@ -76258,7 +76309,7 @@ ${l}`)}es=TW(((o=e.find(([l])=>l==="begriffe.md"))==null?void 0:o[1])??"")}funct

${Be(p("simulation_trace"))}

${Be(p("simulation_variables"))}

${Be(p("simulation_output"))}

- `;const e=a=>this.element.querySelector(a);this.buttons={play:e("[data-sim=play]"),pause:e("[data-sim=pause]"),step:e("[data-sim=step]"),stop:e("[data-sim=stop]")},this.buttons.play.addEventListener("click",()=>this.play()),this.buttons.pause.addEventListener("click",()=>this.pause()),this.buttons.step.addEventListener("click",()=>this.step()),this.buttons.stop.addEventListener("click",()=>this.reset()),this.editButton=e(".sim-edit"),this.editButton.addEventListener("click",()=>this.onEdit());const t=e("[data-sim=highlight]");t.value=this.highlightMode,t.addEventListener("change",()=>{this.highlightMode=t.value,km(Im,this.highlightMode)});const n=e("[data-sim=delay]");n.value=this.delay,n.addEventListener("change",()=>{this.delay=n.value,km(Nr,this.delay)}),this.inputSection=e(".sim-input > div"),this.trace=e(".sim-trace"),this.variables=e(".sim-vars"),this.output=e(".sim-output"),this.notice=e(".sim-notice")}collectOutput(){const e=this.engine.state.outputLines;for(;this.printedr.localeCompare(o));if(n.length===0)this.variables.innerHTML=`

${Be(p("simulation_variables_placeholder"))}

`;else{const r=document.createElement("table");for(const o of n){const l=r.insertRow();l.insertCell().textContent=o;const u=e.variables.get(o),m=l.insertCell();u.kind==="grid"?m.append(Fg(u)):m.textContent=_e(u)}this.variables.replaceChildren(r)}e.outputLines.length===0&&e.files.size===0?this.output.innerHTML=`

${Be(p("simulation_output_placeholder"))}

`:(this.output.replaceChildren(...e.outputLines.map(r=>{const o=document.createElement("div");return o.textContent=r,o}),...Ng(e.files)),this.output.scrollTop=this.output.scrollHeight)}updateInput(){const e=this.engine.state.inputRequest,t=this.inputSection;if(t.parentElement.classList.toggle("active",!!e),!e){t.innerHTML=`

${Be(p("simulation_input_placeholder"))}

`;return}let n=t.querySelector("form");if(!n){n=document.createElement("form"),n.innerHTML=`

`;const l=n.querySelector("input");n.addEventListener("submit",u=>{u.preventDefault(),this.submitInput(l)}),t.replaceChildren(n),requestAnimationFrame(()=>l.focus())}const a=this.engine.state.outputLines;n.querySelector(".sim-prompt").textContent=e.prompt||(a[a.length-1]??"");const s=n.querySelector("input");s.inputMode=e.valueType==="string"||e.valueType==="boolean"?"text":"decimal";const r=this.engine.state.inputErrorNotice,o=n.querySelector(".sim-input-error");o.textContent=r?i1(r):"",o.hidden=!r}}function Fg(i){const e=document.createElement("table");e.className="sim-grid";for(const t of i.value){const n=e.insertRow();for(const a of t){const s=n.insertCell();s.textContent=String(a),a===!0&&(s.className="sim-grid-true")}}return e}const T1=Array.from("ABCDEFGHIJKLMNOPQRSTUVWXYZ"),Vn=360/T1.length,OE="http://www.w3.org/2000/svg";function Re(i,e={},...t){const n=document.createElement(i);for(const[a,s]of Object.entries(e))n.setAttribute(a,s);return n.append(...t),n}function vt(i,e={},t){const n=document.createElementNS(OE,i);for(const[a,s]of Object.entries(e))n.setAttribute(a,String(s));return t!==void 0&&(n.textContent=t),n}function BE(i,e){const t=(e%26+26)%26;return Array.from(i).map(n=>{const a=n.charCodeAt(0);return a>=65&&a<=90?String.fromCharCode((a-65+t)%26+65):a>=97&&a<=122?String.fromCharCode((a-97+t)%26+97):n}).join("")}function Sm(i,e){const t=vt("g",{class:e}),n=T1.map((a,s)=>{const r=vt("g",{transform:`rotate(${s*Vn})`});return r.append(vt("text",{x:0,y:-i,"text-anchor":"middle","dominant-baseline":"central"},a)),t.append(r),r});return{group:t,cells:n}}function ME(i,e){let t=i,n=!1,a=-t*Vn;const s=Re("section",{class:"learn-game learn-caesar"});s.append(Re("div",{class:"learn-game-head"},Re("strong",{},p("web_learn_caesar_title")))),s.append(Re("p",{class:"learn-game-status"},p("web_learn_caesar_hint")));const r=vt("svg",{viewBox:"-200 -200 400 400",class:"learn-caesar-disc",role:"img"});r.append(vt("circle",{r:196,class:"outer-disc"})),r.append(vt("path",{d:ZE(196,92,Vn/2),class:"window"}));const o=Sm(168,"outer-letters");r.append(o.group);for(let C=0;C{o.cells.forEach((L,F)=>L.classList.toggle("marked",F===C)),u.cells.forEach((L,F)=>L.classList.toggle("marked",C!==void 0&&F===(C+t)%26))},k=()=>{m.textContent=String(t),l.setAttribute("transform",`rotate(${a})`),r.setAttribute("aria-label",p("web_learn_caesar_key_fmt",t)),x.textContent=p(n?"web_learn_caesar_secret":"web_learn_caesar_plain"),w.textContent=p(n?"web_learn_caesar_plain":"web_learn_caesar_secret"),f.classList.toggle("active",!n),b.classList.toggle("active",n),z.textContent=BE(v.value,n?-t:t)||" ";const C=Array.from(v.value.toUpperCase()).reverse().find(F=>T1.includes(F));if(C===void 0)return S();const L=T1.indexOf(C);S(n?(L-t+26)%26:L)},P=C=>{t=(C%26+26)%26,a=-t*Vn,k()};c.addEventListener("click",()=>P(t-1)),d.addEventListener("click",()=>P(t+1)),f.addEventListener("click",()=>{var C;n&&(v.value=((C=z.textContent)==null?void 0:C.trim())??""),n=!1,k()}),b.addEventListener("click",()=>{var C;n||(v.value=((C=z.textContent)==null?void 0:C.trim())??""),n=!0,k()}),v.addEventListener("input",k),o.cells.forEach((C,L)=>C.addEventListener("click",()=>S(L)));let D;const A=C=>{const L=r.getBoundingClientRect();return Math.atan2(C.clientY-(L.top+L.height/2),C.clientX-(L.left+L.width/2))*180/Math.PI};l.addEventListener("pointerdown",C=>{const L=C;D=A(L)-a,l.classList.add("dragging"),r.setPointerCapture(L.pointerId),L.preventDefault()}),r.addEventListener("pointermove",C=>{if(D===void 0)return;a=A(C)-D,l.setAttribute("transform",`rotate(${a})`);const L=Math.round(-a/Vn);if((L%26+26)%26!==t){t=(L%26+26)%26;const F=a;k(),a=F,l.setAttribute("transform",`rotate(${a})`)}});const O=()=>{D!==void 0&&(D=void 0,l.classList.remove("dragging"),P(t))};return r.addEventListener("pointerup",O),r.addEventListener("pointercancel",O),k(),s}function ZE(i,e,t){const n=(a,s)=>{const r=(s-90)*Math.PI/180;return`${(a*Math.cos(r)).toFixed(2)} ${(a*Math.sin(r)).toFixed(2)}`};return`M ${n(i,-t)} A ${i} ${i} 0 0 1 ${n(i,t)} L ${n(e,t)} A ${e} ${e} 0 0 0 ${n(e,-t)} Z`}const T0=i=>p(`web_visubot_part_${i}`),Rg=new WeakMap;function Jg(i,e,t,n){const a=document.createElement("div");a.className="visubot-model";const s=document.createElement("div");s.className="visubot-stage";const r=document.createElement("div");r.className="visubot-part-label",r.hidden=!0,s.append(r);const o=(c,d,h)=>{r.hidden=!1,r.textContent=T0(c),r.style.left=`${Math.min(d+12,s.clientWidth-140)}px`,r.style.top=`${h+12}px`},l=document.createElement("p");l.className="visubot-model-hint hint",l.textContent=p("web_visubot_tap_part"),l.hidden=!!n,a.append(s,l);const u=ee(async()=>{const{Robot3D:c}=await import("./robot3d-Dz8gQ3hd.js");return{Robot3D:c}},[],import.meta.url).then(({Robot3D:c})=>{const d=new c(s);d.showcase(),d.highlight(i),i.includes("leds")&&d.setLed([40,90,255]),d.focusOn([],e==="unten"||e==="bottom"?"":e,!1,1),d.focusOn(i,e,t);let h;return s.addEventListener("pointerdown",g=>h={x:g.clientX,y:g.clientY}),s.addEventListener("pointerup",g=>{if(!h||Math.hypot(g.clientX-h.x,g.clientY-h.y)>5)return;const f=d.partAt(g.clientX,g.clientY);if(!f)return;if(n)return n(f);d.highlight(f);const b=s.getBoundingClientRect();o(f,g.clientX-b.left,g.clientY-b.top)}),s.addEventListener("pointermove",g=>{if(g.pointerType!=="mouse"||n)return;const f=d.partAt(g.clientX,g.clientY);if(r.hidden=!f,!f)return;const b=s.getBoundingClientRect();o(f,g.clientX-b.left,g.clientY-b.top)}),s.addEventListener("pointerleave",()=>r.hidden=!0),d}).catch(c=>{console.error(c),s.textContent=p("web_visubot_no_3d")}),m={box:a,ready:u,focus:i,view:e};return Rg.set(a,m),m}function LE(i,e,t=!1){return Jg(i,e,t).box}function WE(i){const e=i.querySelector(".visubot-model"),t=e&&Rg.get(e);for(const n of i.querySelectorAll("[data-robot-part]")){const a=(n.dataset.robotPart??"").split(",").filter(Boolean);if(n.title=a.map(T0).join(", "),!t)continue;const s=()=>void t.ready.then(o=>o==null?void 0:o.highlight(a)),r=()=>void t.ready.then(o=>o==null?void 0:o.highlight(t.focus));n.addEventListener("mouseenter",s),n.addEventListener("focus",s),n.addEventListener("mouseleave",r),n.addEventListener("blur",r),n.addEventListener("click",()=>{t.ready.then(o=>{o==null||o.highlight(a),o==null||o.focusOn(a,t.view)}),t.box.scrollIntoView({block:"nearest",behavior:"smooth"})})}}function EE(i,e){let t=0;const n=document.createElement("div");n.className="visubot-quiz-question";const a=document.createElement("p");a.className="visubot-quiz-feedback",a.setAttribute("aria-live","polite");const s=()=>{n.innerHTML=jn(`**${t+1}/${i.length}** ${i[t].question}`)},r=Jg([],void 0,!1,l=>{if(!(t>=i.length)){if(r.ready.then(u=>u==null?void 0:u.highlight(l)),l!==i[t].part){a.className="visubot-quiz-feedback wrong",a.textContent=p("web_visubot_quiz_wrong_fmt",T0(l));return}t++,a.className="visubot-quiz-feedback right",t{u.forEach(v=>{window.clearTimeout(v),window.clearInterval(v)}),u=[]},c=()=>{a.textContent=`${p("web_game_round_fmt",o+1,r)} · ${p("web_game_score_fmt",l)}`},d=()=>{const v=$("button",{class:"primary"},o+1{o++,o{const v=i.rounds[o],w=i.seconds,z=$("div",{class:"learn-bomb-fuse"},$("span",{})),I=$("span",{class:"learn-bomb-time"}),S=$("div",{class:"learn-bomb","aria-live":"polite"},$("span",{class:"learn-bomb-icon","aria-hidden":"true"},"💣"),I,z),k=$("div",{class:"learn-game-feedback",role:"status"}),P=v.wrongPart!==void 0,D=[],A=v.code.split(` + `;const e=a=>this.element.querySelector(a);this.buttons={play:e("[data-sim=play]"),pause:e("[data-sim=pause]"),step:e("[data-sim=step]"),stop:e("[data-sim=stop]")},this.buttons.play.addEventListener("click",()=>this.play()),this.buttons.pause.addEventListener("click",()=>this.pause()),this.buttons.step.addEventListener("click",()=>this.step()),this.buttons.stop.addEventListener("click",()=>this.reset()),this.editButton=e(".sim-edit"),this.editButton.addEventListener("click",()=>this.onEdit());const t=e("[data-sim=highlight]");t.value=this.highlightMode,t.addEventListener("change",()=>{this.highlightMode=t.value,km(Im,this.highlightMode)});const n=e("[data-sim=delay]");n.value=this.delay,n.addEventListener("change",()=>{this.delay=n.value,km(Nr,this.delay)}),this.inputSection=e(".sim-input > div"),this.trace=e(".sim-trace"),this.variables=e(".sim-vars"),this.output=e(".sim-output"),this.notice=e(".sim-notice")}collectOutput(){const e=this.engine.state.outputLines;for(;this.printedr.localeCompare(o));if(n.length===0)this.variables.innerHTML=`

${Be(p("simulation_variables_placeholder"))}

`;else{const r=document.createElement("table");for(const o of n){const l=r.insertRow();l.insertCell().textContent=o;const u=e.variables.get(o),m=l.insertCell();u.kind==="grid"?m.append(Fg(u)):m.textContent=_e(u)}this.variables.replaceChildren(r)}e.outputLines.length===0&&e.files.size===0?this.output.innerHTML=`

${Be(p("simulation_output_placeholder"))}

`:(this.output.replaceChildren(...e.outputLines.map(r=>{const o=document.createElement("div");return o.textContent=r,o}),...Ng(e.files)),this.output.scrollTop=this.output.scrollHeight)}updateInput(){const e=this.engine.state.inputRequest,t=this.inputSection;if(t.parentElement.classList.toggle("active",!!e),!e){t.innerHTML=`

${Be(p("simulation_input_placeholder"))}

`;return}let n=t.querySelector("form");if(!n){n=document.createElement("form"),n.innerHTML=`

`;const l=n.querySelector("input");n.addEventListener("submit",u=>{u.preventDefault(),this.submitInput(l)}),t.replaceChildren(n),requestAnimationFrame(()=>l.focus())}const a=this.engine.state.outputLines;n.querySelector(".sim-prompt").textContent=e.prompt||(a[a.length-1]??"");const s=n.querySelector("input");s.inputMode=e.valueType==="string"||e.valueType==="boolean"?"text":"decimal";const r=this.engine.state.inputErrorNotice,o=n.querySelector(".sim-input-error");o.textContent=r?i1(r):"",o.hidden=!r}}function Fg(i){const e=document.createElement("table");e.className="sim-grid";for(const t of i.value){const n=e.insertRow();for(const a of t){const s=n.insertCell();s.textContent=String(a),a===!0&&(s.className="sim-grid-true")}}return e}const T1=Array.from("ABCDEFGHIJKLMNOPQRSTUVWXYZ"),Vn=360/T1.length,OE="http://www.w3.org/2000/svg";function Re(i,e={},...t){const n=document.createElement(i);for(const[a,s]of Object.entries(e))n.setAttribute(a,s);return n.append(...t),n}function vt(i,e={},t){const n=document.createElementNS(OE,i);for(const[a,s]of Object.entries(e))n.setAttribute(a,String(s));return t!==void 0&&(n.textContent=t),n}function BE(i,e){const t=(e%26+26)%26;return Array.from(i).map(n=>{const a=n.charCodeAt(0);return a>=65&&a<=90?String.fromCharCode((a-65+t)%26+65):a>=97&&a<=122?String.fromCharCode((a-97+t)%26+97):n}).join("")}function Sm(i,e){const t=vt("g",{class:e}),n=T1.map((a,s)=>{const r=vt("g",{transform:`rotate(${s*Vn})`});return r.append(vt("text",{x:0,y:-i,"text-anchor":"middle","dominant-baseline":"central"},a)),t.append(r),r});return{group:t,cells:n}}function ME(i,e){let t=i,n=!1,a=-t*Vn;const s=Re("section",{class:"learn-game learn-caesar"});s.append(Re("div",{class:"learn-game-head"},Re("strong",{},p("web_learn_caesar_title")))),s.append(Re("p",{class:"learn-game-status"},p("web_learn_caesar_hint")));const r=vt("svg",{viewBox:"-200 -200 400 400",class:"learn-caesar-disc",role:"img"});r.append(vt("circle",{r:196,class:"outer-disc"})),r.append(vt("path",{d:ZE(196,92,Vn/2),class:"window"}));const o=Sm(168,"outer-letters");r.append(o.group);for(let C=0;C{o.cells.forEach((L,F)=>L.classList.toggle("marked",F===C)),u.cells.forEach((L,F)=>L.classList.toggle("marked",C!==void 0&&F===(C+t)%26))},k=()=>{m.textContent=String(t),l.setAttribute("transform",`rotate(${a})`),r.setAttribute("aria-label",p("web_learn_caesar_key_fmt",t)),x.textContent=p(n?"web_learn_caesar_secret":"web_learn_caesar_plain"),w.textContent=p(n?"web_learn_caesar_plain":"web_learn_caesar_secret"),f.classList.toggle("active",!n),b.classList.toggle("active",n),z.textContent=BE(v.value,n?-t:t)||" ";const C=Array.from(v.value.toUpperCase()).reverse().find(F=>T1.includes(F));if(C===void 0)return S();const L=T1.indexOf(C);S(n?(L-t+26)%26:L)},P=C=>{t=(C%26+26)%26,a=-t*Vn,k()};c.addEventListener("click",()=>P(t-1)),d.addEventListener("click",()=>P(t+1)),f.addEventListener("click",()=>{var C;n&&(v.value=((C=z.textContent)==null?void 0:C.trim())??""),n=!1,k()}),b.addEventListener("click",()=>{var C;n||(v.value=((C=z.textContent)==null?void 0:C.trim())??""),n=!0,k()}),v.addEventListener("input",k),o.cells.forEach((C,L)=>C.addEventListener("click",()=>S(L)));let D;const A=C=>{const L=r.getBoundingClientRect();return Math.atan2(C.clientY-(L.top+L.height/2),C.clientX-(L.left+L.width/2))*180/Math.PI};l.addEventListener("pointerdown",C=>{const L=C;D=A(L)-a,l.classList.add("dragging"),r.setPointerCapture(L.pointerId),L.preventDefault()}),r.addEventListener("pointermove",C=>{if(D===void 0)return;a=A(C)-D,l.setAttribute("transform",`rotate(${a})`);const L=Math.round(-a/Vn);if((L%26+26)%26!==t){t=(L%26+26)%26;const F=a;k(),a=F,l.setAttribute("transform",`rotate(${a})`)}});const O=()=>{D!==void 0&&(D=void 0,l.classList.remove("dragging"),P(t))};return r.addEventListener("pointerup",O),r.addEventListener("pointercancel",O),k(),s}function ZE(i,e,t){const n=(a,s)=>{const r=(s-90)*Math.PI/180;return`${(a*Math.cos(r)).toFixed(2)} ${(a*Math.sin(r)).toFixed(2)}`};return`M ${n(i,-t)} A ${i} ${i} 0 0 1 ${n(i,t)} L ${n(e,t)} A ${e} ${e} 0 0 0 ${n(e,-t)} Z`}const T0=i=>p(`web_visubot_part_${i}`),Rg=new WeakMap;function Jg(i,e,t,n){const a=document.createElement("div");a.className="visubot-model";const s=document.createElement("div");s.className="visubot-stage";const r=document.createElement("div");r.className="visubot-part-label",r.hidden=!0,s.append(r);const o=(c,d,h)=>{r.hidden=!1,r.textContent=T0(c),r.style.left=`${Math.min(d+12,s.clientWidth-140)}px`,r.style.top=`${h+12}px`},l=document.createElement("p");l.className="visubot-model-hint hint",l.textContent=p("web_visubot_tap_part"),l.hidden=!!n,a.append(s,l);const u=ee(async()=>{const{Robot3D:c}=await import("./robot3d-ClismEE4.js");return{Robot3D:c}},[],import.meta.url).then(({Robot3D:c})=>{const d=new c(s);d.showcase(),d.highlight(i),i.includes("leds")&&d.setLed([40,90,255]),d.focusOn([],e==="unten"||e==="bottom"?"":e,!1,1),d.focusOn(i,e,t);let h;return s.addEventListener("pointerdown",g=>h={x:g.clientX,y:g.clientY}),s.addEventListener("pointerup",g=>{if(!h||Math.hypot(g.clientX-h.x,g.clientY-h.y)>5)return;const f=d.partAt(g.clientX,g.clientY);if(!f)return;if(n)return n(f);d.highlight(f);const b=s.getBoundingClientRect();o(f,g.clientX-b.left,g.clientY-b.top)}),s.addEventListener("pointermove",g=>{if(g.pointerType!=="mouse"||n)return;const f=d.partAt(g.clientX,g.clientY);if(r.hidden=!f,!f)return;const b=s.getBoundingClientRect();o(f,g.clientX-b.left,g.clientY-b.top)}),s.addEventListener("pointerleave",()=>r.hidden=!0),d}).catch(c=>{console.error(c),s.textContent=p("web_visubot_no_3d")}),m={box:a,ready:u,focus:i,view:e};return Rg.set(a,m),m}function LE(i,e,t=!1){return Jg(i,e,t).box}function WE(i){const e=i.querySelector(".visubot-model"),t=e&&Rg.get(e);for(const n of i.querySelectorAll("[data-robot-part]")){const a=(n.dataset.robotPart??"").split(",").filter(Boolean);if(n.title=a.map(T0).join(", "),!t)continue;const s=()=>void t.ready.then(o=>o==null?void 0:o.highlight(a)),r=()=>void t.ready.then(o=>o==null?void 0:o.highlight(t.focus));n.addEventListener("mouseenter",s),n.addEventListener("focus",s),n.addEventListener("mouseleave",r),n.addEventListener("blur",r),n.addEventListener("click",()=>{t.ready.then(o=>{o==null||o.highlight(a),o==null||o.focusOn(a,t.view)}),t.box.scrollIntoView({block:"nearest",behavior:"smooth"})})}}function EE(i,e){let t=0;const n=document.createElement("div");n.className="visubot-quiz-question";const a=document.createElement("p");a.className="visubot-quiz-feedback",a.setAttribute("aria-live","polite");const s=()=>{n.innerHTML=jn(`**${t+1}/${i.length}** ${i[t].question}`)},r=Jg([],void 0,!1,l=>{if(!(t>=i.length)){if(r.ready.then(u=>u==null?void 0:u.highlight(l)),l!==i[t].part){a.className="visubot-quiz-feedback wrong",a.textContent=p("web_visubot_quiz_wrong_fmt",T0(l));return}t++,a.className="visubot-quiz-feedback right",t{u.forEach(v=>{window.clearTimeout(v),window.clearInterval(v)}),u=[]},c=()=>{a.textContent=`${p("web_game_round_fmt",o+1,r)} · ${p("web_game_score_fmt",l)}`},d=()=>{const v=$("button",{class:"primary"},o+1{o++,o{const v=i.rounds[o],w=i.seconds,z=$("div",{class:"learn-bomb-fuse"},$("span",{})),I=$("span",{class:"learn-bomb-time"}),S=$("div",{class:"learn-bomb","aria-live":"polite"},$("span",{class:"learn-bomb-icon","aria-hidden":"true"},"💣"),I,z),k=$("div",{class:"learn-game-feedback",role:"status"}),P=v.wrongPart!==void 0,D=[],A=v.code.split(` `).map((K,he)=>{if(!P){const M=$("button",{class:"ln",type:"button"},K||" ");return M.disabled=!K.trim(),D.push({button:M,line:he+1,right:he+1===v.wrongLine}),M}const ae=$("div",{class:"ln parts"});K.trim()||ae.append(" ");for(const M of pg(K)){if(!M.part){ae.append(M.text);continue}const j=$("button",{class:"part",type:"button"},M.text);D.push({button:j,line:he+1,right:he+1===v.wrongLine&&M.text===v.wrongPart}),ae.append(j)}return ae});for(const K of D)K.button.addEventListener("click",()=>F(K.right?"right":K.line===v.wrongLine?"part":"wrong",K.button));const O=$("div",{class:`learn-game-code learn-bomb-code mono${P?" by-parts":""}`,dir:"ltr"},...A),C=Date.now(),L=()=>{if(!t.isConnected&&Date.now()-C>1e3)return m();const K=Math.max(0,w-(Date.now()-C)/1e3);I.textContent=p("web_game_time_fmt",Math.ceil(K)),z.firstChild.style.width=`${K/w*100}%`,S.classList.toggle("hurry",K<=5),K<=0&&F("time")},F=(K,he)=>{m();for(const j of D)j.button.disabled=!0,j.right&&j.button.classList.add("right");P&&A[v.wrongLine-1].classList.add("right"),he&&K!=="right"&&he.classList.add("wrong");const ae=K==="right";ae&&l++,c(),S.classList.add(ae?"defused":"boom"),S.firstChild.textContent=ae?"✂️":"💥",k.className=`learn-game-feedback ${ae?"right":"wrong"}`;const M=d();k.replaceChildren($("p",{},p(ae?"web_game_defused":K==="time"?"web_game_boom_time":K==="part"?"web_game_boom_part":P?"web_game_boom_wrong_part":"web_game_boom_wrong")),Gn("div",{class:"learn-game-explain"},v.explanation),$("p",{class:"learn-bomb-fix"},`${p("web_game_fix")} `,$("code",{},v.fix.trim())),M),M.focus({preventScroll:!0})},Y=Gn("p",{class:"learn-game-question"},v.question);P&&Y.append(" ",$("span",{class:"learn-bomb-hint"},p("web_game_bomb_parts_hint"))),s.replaceChildren(S,Y,O,k),L();const ne=window.setInterval(L,200);u.push(ne)},g=()=>{const v=i.rounds[o],w=[];v.code.trim()&&w.push(_m(v.code).element),w.push(Gn("p",{class:"learn-game-question"},v.question),$("p",{class:"learn-order-hint"},p("web_game_order_hint")));const z=$("div",{class:"learn-game-options learn-order"}),I=$("div",{class:"learn-game-feedback",role:"status"});let S=0;const k=FE(v.options.length).map(D=>{const A=$("span",{class:"learn-order-badge","aria-hidden":"true"}),O=$("span",{});O.innerHTML=je(v.options[D].text);const C=$("button",{},A,O);return C.addEventListener("click",()=>{if(D!==S)return C.classList.add("wrong"),P(!1);C.classList.add("right"),A.textContent=String(++S),C.disabled=!0,S===v.options.length&&P(!0)}),z.append(C),{k:D,b:C,badge:A}}),P=D=>{for(const{k:O,b:C,badge:L}of[...k].sort((F,Y)=>F.k-Y.k))C.disabled=!0,L.textContent=String(O+1),z.append(C);D&&l++,c(),I.className=`learn-game-feedback ${D?"right":"wrong"}`;const A=d();I.replaceChildren($("p",{},p(D?"web_game_right":"web_game_wrong_short")),Gn("div",{class:"learn-game-explain"},v.explanation),A),A.focus({preventScroll:!0})};s.replaceChildren(...w,z,I)},f=()=>{if(m(),i.kind==="bombe"||i.kind==="reihenfolge"){c(),i.kind==="bombe"?h():g();return}const v=i.rounds[o];c();const w=_m(v.code),z=[];let I;i.kind==="zuhoerer"?(I=RE(bg(v.code),w),z.push($("div",{class:"learn-swing-row"},w.element,I.element)),v.clicks.length&&z.push($("p",{class:"learn-swing-clicks"},`${p("web_game_clicks")} `,...v.clicks.flatMap((A,O)=>[...O?[" → "]:[],$("code",{},A)])))):v.code.trim()&&z.push(w.element),z.push(Gn("p",{class:"learn-game-question"},v.question));const S=$("div",{class:`learn-game-options ${i.kind==="layout"?"pictures":""}`}),k=$("div",{class:"learn-game-feedback",role:"status"}),P=v.options.map(A=>{const O=$("button",{});return i.kind==="layout"?O.append(GE(A.text)):A.text.includes(` `)?O.append(JE(A.text)):O.innerHTML=je(A.text),O.addEventListener("click",()=>D(A.right,O)),S.append(O),O}),D=(A,O)=>{P.forEach((L,F)=>{L.disabled=!0,v.options[F].right&&L.classList.add("right")}),A||O.classList.add("wrong"),A&&l++,c(),k.className=`learn-game-feedback ${A?"right":"wrong"}`;const C=d();k.replaceChildren($("p",{},p(A?"web_game_right":"web_game_wrong_short")),Gn("div",{class:"learn-game-explain"},v.explanation)),k.append(C),I&&(u=I.replay(v.clicks,()=>C.before($("p",{class:"learn-swing-try"},p("web_game_try"))))),C.focus({preventScroll:!0})};s.replaceChildren(...z,S,k)},b=()=>{m(),a.textContent="";const v=$("button",{class:"primary"},p("web_game_again"));v.addEventListener("click",()=>{o=l=0,f()}),s.replaceChildren($("p",{class:"learn-game-result"},p("web_game_done_fmt",l,r)),$("p",{},p(l===r?"web_game_perfect":l>=r*.7?"web_game_good":"web_game_practice_short")),v)},x=$("button",{class:"primary"},p("web_game_start"));return x.addEventListener("click",f),s.append(Gn("p",{},i.intro),x),t}function FE(i){const e=[...Array(i).keys()];for(;e.every((t,n)=>t===n);)for(let t=i-1;t>0;t--){const n=Math.floor(Math.random()*(t+1));[e[t],e[n]]=[e[n],e[t]]}return e}function _m(i){const e=i.split(` `).map(n=>$("div",{class:"ln"},n||" "));return{element:$("pre",{class:"learn-game-code mono",dir:"ltr"},...e),highlight(n,a){e.forEach((s,r)=>s.classList.toggle("hit",n!==void 0&&r>=n&&r<=(a??n)))}}}function RE(i,e){const t=xg(i),n=$("div",{class:"learn-swing-window",dir:"ltr"});n.append($("div",{class:"learn-swing-title"},i.title||" "));const a=$("div",{class:"learn-swing-body"}),s=new Map;for(const c of i.labels){const d=$("div",{class:"learn-swing-label"},t.texts[c.name]);s.set(c.name,d),a.append(d)}const r=i.buttons.map(c=>{const d=$("button",{class:"learn-swing-button",disabled:""},t.texts[c.name]);return s.set(c.name,d),a.append(d),d}),o=$("p",{class:"learn-swing-event",role:"status"}),l=$("pre",{class:"learn-swing-console mono",hidden:""});n.append(a,o,l);const u=c=>{var h,g;const d=s.get(c.button);d.classList.add("pressed"),window.setTimeout(()=>d.classList.remove("pressed"),350),e.highlight((h=c.listener)==null?void 0:h.from,(g=c.listener)==null?void 0:g.to),o.textContent=c.listener?p("web_game_event_fmt",d.textContent??""):p("web_game_nobody"),o.className=`learn-swing-event ${c.listener?"heard":"nobody"}`;for(const[f,b]of Object.entries(c.texts)){const x=s.get(f);x&&x.textContent!==b&&(x.textContent=b,x.classList.remove("changed"),x.offsetWidth,x.classList.add("changed"))}c.console.length&&(l.hidden=!1,l.textContent+=c.console.map(f=>`${f} @@ -76274,7 +76325,7 @@ ${l}`)}es=TW(((o=e.find(([l])=>l==="begriffe.md"))==null?void 0:o[1])??"")}funct ${a}`));this.body.append(s),this.foldReference(s)}}foldReference(e){const t="visustruct.reference.open";let n=[];try{n=JSON.parse(localStorage.getItem(t)??"[]")}catch{}for(const a of[...e.querySelectorAll("h2")]){const s=a.textContent??"",r=_("details",{class:"reference-group"});r.open=n.includes(s);const o=_("summary",{},s);for(a.replaceWith(r),r.append(o);r.nextSibling&&r.nextSibling.nodeName!=="H2";)r.append(r.nextSibling);r.addEventListener("toggle",()=>{n=r.open?[...new Set([...n,s])]:n.filter(l=>l!==s);try{localStorage.setItem(t,JSON.stringify(n))}catch{}})}}showReference(){this.tab="reference",this.persist(),this.render()}persist(){xe.setView({tab:this.tab,lesson:this.lessonId,task:this.taskId})}showLesson(e){zt.some(t=>t.id===e)&&this.openLesson(e)}openLesson(e){this.tab="lessons",this.lessonId=e,this.returnTo=void 0,this.persist(),this.render(),this.body.scrollTop=0}renderLessonList(){this.body.append(_("p",{class:"hint"},p("web_learn_intro")));for(const e of cN()){this.body.append(_("h3",{class:"learn-section"},e.name));const t=_("ol",{class:"learn-list"});for(const n of e.lessons){const a=xe.lesson(n.id),s=a.done?"✓":a.step>0?p("web_learn_step_of_fmt",a.step+1,n.steps.length):"",r=_("button",{class:"learn-item"+(a.done?" done":""),"data-lesson":n.id},_("span",{class:"learn-num"},String(n.number)),_("span",{class:"learn-item-text"},_("strong",{},n.robot?`🤖 ${n.title}`:n.title),_("small",{},n.summary)),_("span",{class:"learn-status"},s));r.addEventListener("click",()=>this.openLesson(n.id)),t.append(_("li",{},r))}this.body.append(t)}this.body.append(this.renderTeacherBox())}renderLesson(e){var u;const t=xe.lesson(e.id),n=Math.min(t.step,e.steps.length-1),a=e.steps[n],s=_("button",{class:"learn-back"},`← ${p("web_learn_all_lessons")}`);s.addEventListener("click",()=>this.openLesson(void 0));const r=_("nav",{class:"learn-progress","aria-label":p("web_learn_step_of_fmt",n+1,e.steps.length)});r.append(...e.steps.map((m,c)=>{const d=p("web_learn_step_fmt",c+1,m.title),h=cthis.goToStep(e,c)),g})),this.body.append(_("div",{class:"learn-lesson-head"},_("div",{class:"learn-head-row"},s,this.stepNav(e,n,t.done,"learn-nav learn-nav-top")),_("p",{class:"learn-kicker"},`${p("web_learn_lesson_fmt",e.number)} · ${e.section}${e.robot?" · 🤖 VisuBot":""}`),_("h2",{class:"learn-title"},_("span",{class:"learn-num","aria-hidden":"true"},String(e.number)),e.title),r,_("h3",{class:"learn-step-title"},`${n+1}. ${a.title}`)));const o=((u=this.returnTo)==null?void 0:u.lesson)===e.id&&this.returnTo.step!==n?this.returnTo:void 0,l=()=>{const m=_("button",{class:"learn-return"},`↩ ${p("web_learn_back_to_checklist")}`);return m.addEventListener("click",()=>{this.returnTo=void 0,this.goToStep(e,o.step),this.body.scrollTop=o.scroll}),m};o&&this.body.append(l()),a.blocks.forEach((m,c)=>this.body.append(this.renderBlock(m,`${n}-${c}`,e))),Om(this.body),WE(this.body),this.openNeededColumns(a.blocks),Pm(this.body,es),this.body.append(this.stepNav(e,n,t.done,"learn-nav")),o&&this.body.append(l())}stepNav(e,t,n,a){const s=_("div",{class:a}),r=_("button",{},`← ${p("web_learn_back")}`);if(r.disabled=t===0,r.addEventListener("click",()=>this.goToStep(e,t-1)),s.append(r),tthis.goToStep(e,t+1)),s.append(o)}else{const o=_("button",{class:"primary"},n?`✓ ${p("web_learn_done")}`:p("web_learn_finish"));o.addEventListener("click",()=>{xe.updateLesson(e.id,{done:!0});const l=zt.find(u=>u.number===e.number+1);this.openLesson(l==null?void 0:l.id)}),s.append(o)}return s}goToStep(e,t){xe.updateLesson(e.id,{step:t}),this.render(),this.body.scrollTop=0}openNeededColumns(e){const t=e.flatMap(n=>n.kind==="exercise"?[n.exercise]:[]);lN(this.body)?(this.host.showEditor(),rN(this.body)&&this.host.reveal(["palette"])):oN(this.body)?this.host.showFiles():t.some(n=>n.code!=="java")?this.host.showEditor():(t.length>0||this.body.querySelector(".lesson-code[data-lang=java]"))&&this.host.showJava(),uN(this.body)&&this.host.showLiveCode()}renderTaskList(){this.body.append(_("p",{class:"hint"},p("web_learn_tasks_intro")));const e=_("ul",{class:"learn-list"});for(const t of Pn){const n=this.taskExercises(t),a=n.length>0&&n.every(o=>xe.exercise(o.id).done),s=zt.find(o=>o.number===t.after),r=_("button",{class:"learn-item"+(a?" done":""),"data-task":t.id},_("span",{class:"learn-num","aria-label":p("web_learn_level_fmt",t.level)},"★".repeat(t.level)),_("span",{class:"learn-item-text"},_("strong",{},t.title),_("small",{},s?p("web_learn_after_fmt",s.number,s.title):"")),_("span",{class:"learn-status"},a?"✓":""));r.addEventListener("click",()=>{this.taskId=t.id,this.persist(),this.render(),this.body.scrollTop=0}),e.append(_("li",{},r))}this.body.append(e,this.renderTeacherBox())}renderTeacherBox(){const e=_("details",{class:"learn-teacher"},_("summary",{},p("web_learn_teacher")));if(wm()){e.setAttribute("open","");const s=_("button",{},p("web_learn_teacher_off"));return s.addEventListener("click",()=>{AE(),this.render()}),e.append(_("p",{},p("web_learn_teacher_on")),s),e}const t=_("input",{type:"password",autocomplete:"off","aria-label":p("web_learn_teacher_code"),placeholder:p("web_learn_teacher_code")}),n=_("p",{class:"learn-result",role:"status"}),a=_("form",{class:"group"},t,_("button",{type:"submit"},p("web_learn_teacher_unlock")));return a.addEventListener("submit",async s=>{s.preventDefault(),await CE(t.value)?this.render():(n.className="learn-result info",n.textContent=p("web_learn_teacher_wrong"))}),e.append(_("p",{class:"hint"},p("web_learn_teacher_intro")),a,n),e}taskExercises(e){return e.blocks.flatMap(t=>t.kind==="exercise"?[t.exercise]:[])}renderTask(e){const t=_("button",{class:"learn-back"},`← ${p("web_learn_all_tasks")}`);t.addEventListener("click",()=>{this.taskId=void 0,this.persist(),this.render()});const n=zt.find(a=>a.number===e.after);if(this.body.append(t,_("h2",{class:"learn-title"},e.title)),n){const a=_("button",{class:"link-button"},p("web_learn_after_fmt",n.number,n.title));a.addEventListener("click",()=>this.openLesson(n.id)),this.body.append(_("p",{class:"learn-kicker"},a))}e.blocks.forEach((a,s)=>this.body.append(this.renderBlock(a,`task-${s}`))),Om(this.body),this.openNeededColumns(e.blocks),Pm(this.body,es)}renderBlock(e,t,n){switch(e.kind){case"markdown":return this.withOpenButtons(Ve("div",{class:"learn-text"},jn(e.text)));case"diagram":return this.renderDiagram(e.file,e.caption);case"exercise":return this.renderExercise(e.exercise);case"competences":return this.renderCompetences(e.items);case"checklist":return this.renderChecklist(e.items,t,n);case"quiz":return this.renderQuiz(e.questions,t,n);case"brag":return this.renderBrag(e.text,e.tip);case"images":return this.renderImages(e.files,e.caption);case"graphic":return e.animated?this.renderAnimation(e.file,e.caption):this.renderGraphic(e.file,e.caption,e.labeled);case"game":return this.renderGame(e.game);case"roundGame":return NE(e.game,x1);case"rescueGame":return HE(e.game,x1);case"driveGame":return YE(e.game,x1);case"crosswordGame":return VE(e.game,x1);case"caesar":return ME(e.key,e.text);case"cloze":return $E(e.cloze);case"pap":return iN(e.pap);case"textFile":return Eg(e.name,e.content);case"robotModel":return LE(e.focus,e.view,e.spin);case"robotQuiz":return EE(e.tasks,e.done)}}renderBrag(e,t=!1){const n=_("aside",{class:"learn-brag"});n.append(_("img",{src:x1,alt:"",width:"48",height:"48"}));const a=_("div",{},_("p",{class:"learn-brag-title"},p(t?"web_learn_ludwig_tip":"web_learn_brag")));return a.append(Ve("div",{class:"learn-text"},jn(e))),n.append(a),n}renderGame(e){const n=_("section",{class:"learn-game"}),a=_("div",{class:"learn-game-head"});a.append(_("img",{src:x1,alt:"",width:"40",height:"40"}),_("strong",{},p("web_game_title")));const s=_("p",{class:"learn-game-status"}),r=_("div",{class:"learn-game-stage"});n.append(a,s,r);let o=0,l=0;const u=()=>{const d=e4(e,o,10);s.textContent=`${p("web_game_round_fmt",o+1,10)} · ${p("web_game_score_fmt",l)}`;const h=_("div",{class:"learn-game-values mono"});for(const[w,z]of t4(d))h.append(_("code",{},`${w} = ${z}`));const g=_("div",{class:"group learn-game-answers"}),f=_("button",{class:"learn-game-true"},`✓ ${p("web_game_true")}`),b=_("button",{class:"learn-game-false"},`✗ ${p("web_game_false")}`);g.append(f,b);const x=_("div",{class:"learn-game-feedback",role:"status"}),v=w=>{f.disabled=b.disabled=!0;const z=w===d.answer;z&&l++,s.textContent=`${p("web_game_round_fmt",o+1,10)} · ${p("web_game_score_fmt",l)}`,x.className=`learn-game-feedback ${z?"right":"wrong"}`;const I=_("div",{class:"learn-game-steps mono"});Xx(d.condition,d.values).forEach((k,P)=>I.append(_("div",{},`${P?"→ ":""}${k}`)));const S=_("button",{class:"primary"},o+1<10?p("web_game_next"):p("web_game_finish"));S.addEventListener("click",()=>{o++,o<10?u():m()}),x.replaceChildren(_("p",{},p(z?"web_game_right":"web_game_wrong")),I,S),S.focus()};f.addEventListener("click",()=>v(!0)),b.addEventListener("click",()=>v(!1)),r.replaceChildren(h,_("div",{class:"learn-game-condition mono"},d.condition),g,x)},m=()=>{s.textContent="";const d=_("button",{class:"primary"},p("web_game_again"));d.addEventListener("click",()=>{o=l=0,u()}),r.replaceChildren(_("p",{class:"learn-game-result"},p("web_game_done_fmt",l,10)),_("p",{},p(l===10?"web_game_perfect":l>=10*.7?"web_game_good":"web_game_practice")),d)},c=_("button",{class:"primary"},p("web_game_start"));return c.addEventListener("click",u),r.append(_("p",{},p("web_game_intro")),c),n}renderImages(e,t){const n=_("figure",{class:"learn-figure"}),a=_("div",{class:"learn-images"});for(const s of e){const r=va(s);r&&a.append(_("img",{src:r,alt:"",loading:"lazy"}))}return n.append(a),t&&n.append(Ve("figcaption",{},je(t))),n}renderGraphic(e,t,n){const a=_("figure",{class:"learn-figure"}),s=va(e),r=n?va(n):void 0;if(s&&r){const o=_("img",{class:"learn-graphic",src:s,alt:"",loading:"lazy"}),l=_("button",{class:"learn-graphic-toggle",type:"button",title:p("web_learn_graphic_labels"),"aria-pressed":"false"},o);l.addEventListener("click",()=>{const u=l.getAttribute("aria-pressed")!=="true";l.setAttribute("aria-pressed",String(u)),o.src=u?r:s}),a.append(l,_("p",{class:"learn-graphic-hint"},p("web_learn_graphic_labels")))}else s&&a.append(_("img",{class:"learn-graphic",src:s,alt:"",loading:"lazy"}));return t&&a.append(Ve("figcaption",{},je(t))),a}renderAnimation(e,t){const n=_("figure",{class:"learn-figure"}),a=va(e);if(!a)return n;const s=_("div",{class:"learn-graphic learn-animation"}),r=_("button",{class:"learn-replay",type:"button"},`↻ ${p("web_learn_replay")}`);let o=()=>{};return fetch(a).then(l=>l.text()).then(l=>{var d,h;s.innerHTML=l;const u=s.querySelector("svg"),m=(h=(d=u==null?void 0:u.getAttribute("class"))==null?void 0:d.match(/(\S+-)svg\b/))==null?void 0:h[1];if(!u||!m)return;if(o=()=>{u.classList.remove(`${m}play`),u.getBoundingClientRect(),u.classList.add(`${m}play`)},typeof IntersectionObserver>"u")return o();const c=new IntersectionObserver(g=>{g.some(f=>f.isIntersecting)&&(c.disconnect(),o())},{threshold:.6});c.observe(s)}).catch(()=>s.append(_("img",{src:a,alt:""}))),r.addEventListener("click",()=>o()),n.append(s,r),t&&n.append(Ve("figcaption",{},je(t))),n}withOpenButtons(e){for(const t of e.querySelectorAll("pre.lesson-code[data-open=editor]")){const n=t.textContent??"",a=_("button",{class:"learn-open-code"},p("web_learn_open_in_editor"));a.addEventListener("click",()=>this.host.openJavaCode(n)),t.after(a)}return e}renderDiagram(e,t){const n=di(e),a=_("figure",{class:"learn-figure"});if(!n)return a;const s=this.host.preview(n);s&&a.append(_("div",{class:"learn-preview",dir:"ltr"},s)),t&&a.append(Ve("figcaption",{},je(t)));const r=_("button",{},p("web_learn_open_in_editor"));return r.addEventListener("click",()=>this.host.openDiagram(n,e)),a.append(r),a}renderExercise(e){const t=_("section",{class:"learn-exercise","data-exercise":e.id}),n=()=>xe.exercise(e.id),a=_("span",{class:"learn-badge"},`✓ ${p("web_learn_solved")}`);a.hidden=!n().done,t.append(_("h4",{},`${p("web_learn_exercise")}: ${e.title}`,a),pN(e),Ve("div",{class:"learn-text"},jn(e.task)));const s=_("div",{class:"learn-result",role:"status"}),r=_("div",{class:"learn-hints"}),o=_("div",{class:"group"}),l=_("button",{class:"primary"},p("web_learn_open_exercise"));l.addEventListener("click",()=>{const c=n().xml;let d=Bm(e);if(c)try{d=n0(c)}catch{}this.host.openExercise(e,d)});const u=_("button",{},p("web_learn_check"));if(u.addEventListener("click",()=>{const c=this.host.exerciseDocument(e.id);if(!c){s.className="learn-result info",s.textContent=p("web_learn_open_first");return}if(c.elements.every(Xl)){s.className="learn-result info",s.textContent=p("web_learn_empty");return}this.host.stopSimulation();const d=qx(c,e.tests,this.host.subprogramsFor(e.id),ts),h=Qx(c),g=e.requires.map(x=>x==="forZaehlSchleife"?"forSchleife":x).filter(x=>x in T&&!h.has(T[x])),f=e.loopDepth!==void 0&&Yo(c.elements)x.passed)&&g.length===0&&!f;this.showResult(s,d,g,b,f),b&&(xe.updateExercise(e.id,{done:!0}),a.hidden=!1)}),o.append(l,u),e.hints.length>0){const c=_("button",{},p("web_learn_hint"));c.addEventListener("click",()=>{const d=r.children.length;if(d>=e.hints.length)return;const h=e.hints.length>1?`**${p("web_learn_hint_fmt",d+1,e.hints.length)}:** `:"";r.append(Ve("aside",{class:"lesson-note"},jn(h+e.hints[d]))),c.textContent=p("web_learn_hint_more"),c.toggleAttribute("disabled",d+1>=e.hints.length)}),o.append(c)}const m=_("button",{class:"danger-text"},p("web_learn_reset"));if(m.addEventListener("click",()=>{if(m.dataset.confirm!=="1"){m.dataset.confirm="1",m.textContent=p("web_learn_reset_confirm"),setTimeout(()=>{m.dataset.confirm="",m.textContent=p("web_learn_reset")},4e3);return}xe.resetExercise(e.id),this.host.resetExercise(e.id,Bm(e)),a.hidden=!0,s.replaceChildren(),s.className="learn-result",m.dataset.confirm="",m.textContent=p("web_learn_reset")}),o.append(m),t.append(o,r,s),wm()&&e.solution){const c=di(e.solution);if(c){const d=_("details",{class:"learn-solution"},_("summary",{},p("web_learn_solution")));d.addEventListener("toggle",()=>{if(!d.open||d.querySelector(".learn-preview"))return;const h=this.host.preview(c);h&&d.append(_("div",{class:"learn-preview",dir:"ltr"},h));const g=_("button",{},p("web_learn_open_in_editor"));g.addEventListener("click",()=>{this.host.openDiagram(c,e.solution);for(const f of e.subprograms){const b=di(f);b&&this.host.openDiagram(b,f)}});for(const f of e.subprograms){const b=di(f),x=b&&this.host.preview(b);x&&d.append(_("div",{class:"learn-preview",dir:"ltr"},x))}d.append(g)}),t.append(d)}}return t}showResult(e,t,n,a,s){var o,l,u,m,c;e.className="learn-result "+(a?"ok":"fail"),e.replaceChildren(_("p",{class:"learn-result-head"},a?`🎉 ${p("web_learn_passed")}`:p("web_learn_failed")));for(const d of n)e.append(_("p",{},`✗ ${p("web_learn_missing_fmt",dN(T[d]))}`));s&&e.append(_("p",{},`✗ ${p("web_visubot_depth_fmt",s)}`));const r=_("ul",{class:"learn-tests",dir:"auto"});for(const d of t){const h=d.test.world?t.filter(x=>x.test.world).indexOf(d)+1:0,g=d.test.world?`🗺 ${p("web_visubot_world_fmt",h)}`:d.test.actions?`🤖 ${p("web_visubot_actions")}`:d.test.sensors?`🎛 ${Object.entries(d.test.sensors).map(([x,v])=>`mbot.${x}() = ${v.join(" → ")}`).join(", ")}`:d.test.drive?`🤖 ${p("web_visubot_drive")}`:d.test.inputs.length?p("web_learn_input_fmt",d.test.inputs.join(", ")):p("web_learn_no_input"),f=[`${d.passed?"✓":"✗"} ${g}`],b=_("div",{class:"learn-test-detail"});if(d.test.drive&&b.append(_("span",{},`${p("web_learn_expected")}: `,_("code",{},mi(d.test.drive)||"–")),_("span",{},`${p("web_learn_actual")}: `,_("code",{},mi(d.result.drive??[])||"–"))),d.test.actions&&b.append(_("span",{},`${p("web_learn_expected")}: `,_("code",{},mi(d.test.actions)||"–")),_("span",{},`${p("web_learn_actual")}: `,_("code",{},mi(d.result.actions??[])||"–"))),d.test.led!==void 0){const x=v=>p(v?"web_visubot_led_on":"web_visubot_led_off");b.append(_("span",{},`💡 ${p("web_learn_expected")}: ${x(d.test.led)} · ${p("web_learn_actual")}: ${x(d.result.led)}`))}if(d.test.tone!==void 0){const x=v=>p(v?"web_visubot_tone_yes":"web_visubot_tone_no");b.append(_("span",{},`🔊 ${p("web_learn_expected")}: ${x(d.test.tone)} · ${p("web_learn_actual")}: ${x(d.result.tone)}`))}d.test.screen!==void 0&&b.append(_("span",{},`📺 ${p("web_learn_expected")}: `,_("code",{},d.test.screen),` · ${p("web_learn_actual")}: `,_("code",{},d.result.screen??"–"))),d.test.world&&(((l=(o=ts(d.test.world))==null?void 0:o.goals)!=null&&l.length||(m=(u=ts(d.test.world))==null?void 0:u.targets)!=null&&m.length)&&b.append(_("span",{},d.result.atGoal?`✓ ${p("web_visubot_goal_reached")}`:`✗ ${p("web_visubot_goal_missed")}`)),d.result.bumps&&b.append(_("span",{class:"learn-error"},`⚠︎ ${p("web_visubot_bumps")}: ${d.result.bumps}`))),(!d.test.drive&&!d.test.world&&!d.test.sensors&&!d.test.actions||d.result.outputs.length)&&b.append(_("span",{},`${p("web_learn_expected")}: `,_("code",{},d.test.expected.join(" | ")||"–")),_("span",{},`${p("web_learn_actual")}: `,_("code",{},d.result.outputs.join(" | ")||"–")));for(const x of d.test.files??[])b.append(_("span",{},`📄 ${x.name}, ${p("web_learn_expected")}: `,_("code",{},x.lines.join(" | ")||"–")),_("span",{},`📄 ${x.name}, ${p("web_learn_actual")}: `,_("code",{},gg((c=d.result.files)==null?void 0:c.get(x.name)).join(" | ")||"–")));!d.passed&&!d.result.error&&Vx(d.result.outputs,d.test.expected)&&b.append(_("span",{class:"learn-error"},p("web_learn_missing_line_break"))),d.result.error&&b.append(_("span",{class:"learn-error"},i1(d.result.error))),d.result.missingInput&&b.append(_("span",{class:"learn-error"},p("web_learn_missing_input"))),d.result.tooManySteps&&b.append(_("span",{class:"learn-error"},p("web_learn_too_many_steps"))),!d.passed&&d.result.unusedInputs&&b.append(_("span",{class:"learn-error"},p("web_learn_unused_input"))),r.append(_("li",{class:d.passed?"ok":"fail"},...f,b))}e.append(r)}renderCompetences(e){const t=_("aside",{class:"learn-competences"},_("p",{class:"learn-competences-title"},p("web_learn_competences_intro"))),n=_("ul",{});for(const a of e)n.append(Ve("li",{},je(a)));return t.append(n),t}renderChecklist(e,t,n){const a=[{value:"umbrella",icon:"☂️",label:p("web_learn_rating_umbrella")},{value:"cloud",icon:"⛅",label:p("web_learn_rating_cloud")},{value:"sun",icon:"☀️",label:p("web_learn_rating_sun")}],s=_("div",{class:"learn-checklist-wrap"}),r=_("p",{class:"learn-rating-legend"});for(const l of a)r.append(_("span",{},`${l.icon} ${l.label}`));const o=_("ul",{class:"learn-checklist"});return s.append(r,o),e.forEach((l,u)=>{var v;const m=`${t}-${u}`,c=n?(v=xe.lesson(n.id).checks)==null?void 0:v[m]:void 0;let d=c===!0?"sun":c||void 0;const h=Ve("span",{class:"learn-check-text"},je(l.text)),g=_("span",{class:"learn-rating",role:"group","aria-label":h.textContent??""}),f=a.map(w=>{const z=_("button",{class:"learn-rating-button",title:w.label,"aria-label":w.label},w.icon);return z.addEventListener("click",()=>{if(d=d===w.value?void 0:w.value,b(),!n)return;const I={...xe.lesson(n.id).checks??{}};d?I[m]=d:delete I[m],xe.updateLesson(n.id,{checks:Object.keys(I).length?I:void 0})}),z}),b=()=>{f.forEach((w,z)=>w.setAttribute("aria-pressed",String(a[z].value===d))),x.dataset.rating=d??""};g.append(...f);const x=_("li",{},h,g);if(n&&l.step!==void 0){const w=l.step,z=p("web_learn_step_fmt",w+1,n.steps[w].title),I=_("button",{class:"link-button learn-check-link",title:z,"aria-label":`${p("web_learn_review")}: ${z}`},p("web_learn_review"));I.addEventListener("click",()=>{this.returnTo={lesson:n.id,step:xe.lesson(n.id).step,scroll:this.body.scrollTop},this.goToStep(n,w)}),x.append(I)}b(),o.append(x)}),s}renderQuiz(e,t,n){const a=_("div",{class:"learn-quiz"}),s=_("p",{class:"learn-score",role:"status"}),r=()=>n?xe.lesson(n.id).quiz??{}:{},o=_("div",{class:"learn-review"}),l=()=>{const u=r(),m=(f,b)=>f.pairs?f.pairs.every((x,v)=>u[`${t}-${b}-${v}`]!==void 0):u[`${t}-${b}`]!==void 0,c=(f,b)=>{var x;return!!(f.pairs?f.pairs.every((v,w)=>Mm(f)[u[`${t}-${b}-${w}`]]===f.pairs[w].right):(x=f.options[u[`${t}-${b}`]])!=null&&x.correct)},d=e.filter(m).length,h=e.filter(c).length,g=d===e.length;s.textContent=g?p("web_learn_score_fmt",h,e.length):"",o.replaceChildren(),g&&n&&this.fillChecklistReview(o,n,e,f=>c(e[f],f))};return e.forEach((u,m)=>{const c=`${t}-${m}`,d=_("fieldset",{},Ve("legend",{},je(u.question))),h=Ve("p",{class:"learn-explanation"},je(u.explanation??""));if(u.pairs){d.append(this.renderMatch(u,c,r,n,h,l),h),a.append(d);return}const g=f=>{d.querySelectorAll("button").forEach((b,x)=>{b.classList.toggle("right",f!==void 0&&u.options[x].correct),b.classList.toggle("wrong",f===x&&!u.options[x].correct),b.setAttribute("aria-pressed",String(f===x))}),h.hidden=f===void 0||!u.explanation};u.options.forEach((f,b)=>{const x=Ve("button",{class:"learn-option"},je(f.text));x.addEventListener("click",()=>{n&&xe.updateLesson(n.id,{quiz:{...r(),[c]:b}}),g(b),l()}),d.append(x)}),d.append(h),g(r()[c]),a.append(d)}),a.append(s,o),l(),a}fillChecklistReview(e,t,n,a){const s={sun:"☀️",cloud:"⛅",umbrella:"☂️"},r=xe.lesson(t.id).checks??{},o=[];let l=0;t.steps.forEach((u,m)=>u.blocks.forEach((c,d)=>{c.kind==="checklist"&&c.items.forEach((h,g)=>{const f=r[`${m}-${d}-${g}`],b=f===!0?"sun":f||void 0,x=h.step===void 0?[]:n.map((S,k)=>S.step===h.step?k:-1).filter(S=>S>=0),v=x.filter(S=>!a(S));let w="";b==="sun"&&v.length?w=p("web_learn_review_overrated_fmt",v.map(S=>S+1).join(", ")):b&&b!=="sun"&&x.length&&!v.length&&(w=p("web_learn_review_underrated")),w&&l++;const z=_("li",{class:w?"learn-review-deviation":""}),I=Ve("span",{class:"learn-check-text"},je(h.text));if(w&&I.append(_("br",{}),_("em",{},w)),z.append(I,_("span",{class:"learn-review-icon","aria-label":p(b?`web_learn_rating_${b}`:"web_learn_review_unrated")},b?s[b]:"–")),w&&b==="sun"&&h.step!==void 0){const S=h.step,k=_("button",{class:"link-button learn-check-link"},p("web_learn_review"));k.addEventListener("click",()=>{this.returnTo={lesson:t.id,step:xe.lesson(t.id).step,scroll:this.body.scrollTop},this.goToStep(t,S)}),z.append(k)}o.push(z)})})),o.length&&e.append(_("p",{class:"learn-review-title"},`📋 ${p("web_learn_review_title")}`),_("p",{},p(l?"web_learn_review_hint":"web_learn_review_match")),_("ul",{class:"learn-checklist"},...o))}renderMatch(e,t,n,a,s,r){const o=e.pairs,l=Mm(e),u=_("div",{class:"learn-match"});let m={};const c=()=>a?n():m,d=b=>a?xe.updateLesson(a.id,{quiz:b}):m=b,h=b=>c()[`${t}-${b}`],g=o.map(b=>{const x=_("select",{class:"learn-match-select"});x.append(_("option",{value:""},"–")),l.forEach((w,z)=>x.append(_("option",{value:String(z)},w)));const v=Ve("label",{class:"learn-match-left"},je(b.left));return v.append(x),u.append(v),x}),f=()=>{const b=o.every((x,v)=>h(v)!==void 0);g.forEach((x,v)=>{const w=h(v);x.value=w===void 0?"":String(w),x.classList.toggle("right",b&&l[w]===o[v].right),x.classList.toggle("wrong",b&&l[w]!==o[v].right)}),s.hidden=!b||!e.explanation};return g.forEach((b,x)=>b.addEventListener("change",()=>{const v={...c()};b.value===""?delete v[`${t}-${x}`]:v[`${t}-${x}`]=Number(b.value),d(v),f(),r()})),f(),u}}function Mm(i){return(i.pairs??[]).map(e=>e.right).sort((e,t)=>e.localeCompare(t,"de"))}function pN(i){const e=Pg(i),t=e==="beide"?"web_learn_solve_in_both":e==="code"?"web_learn_solve_in_code":"web_learn_solve_in_editor",n={editor:p("web_editor_title"),code:p("web_live_title")},a=e==="beide"?["editor","code"]:[e==="code"?"code":"editor"],s=_("p",{class:`learn-where learn-where-${e}`});for(const r of p(t,...a).split(/(\u0001(?:editor|code))/))if(r==="editor"||r==="code"){const o=r.slice(1);s.append(_("span",{class:`area-name area-${o}`},n[o]))}else r&&s.append(r);return s}const fN=""+new URL("visubot-CyGFOI9V.webp",import.meta.url).href,hr="visustruct.visubot";function gr(){try{return localStorage.getItem(hr)}catch{return null}}function wi(){const i=gr();return i==="1"||i==="kurs"?"on":"off"}const Ug=()=>gr()==="2";function tl(){try{localStorage.setItem(hr,"2")}catch{}}const Yg=()=>gr()==="3";function $g(){try{localStorage.setItem(hr,"3")}catch{}}const Xg=()=>gr()!==null;function ns(i){try{localStorage.setItem(hr,i==="on"?"1":"0")}catch{}}const bN=`VisuBot`,qn=()=>wi()!=="off",Zm=i=>i.replace(/[&<>"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e]);function nl(){const i=Ug()?"object":Yg()?"flow":wi(),e=(n,a)=>``,t={off:"web_visubot_world_visustruct_hint",on:"web_visubot_world_visubot_hint",object:"web_visuobject_world_hint",flow:"web_visuflow_world_hint"}[i];return`
${e("off","VisuStruct")}${e("on","VisuBot")}${e("object","VisuObject")}${e("flow","VisuFlow")}
- ${Zm(p(t))}`}class xN{constructor(e=Mi){y(this,"element");y(this,"world");y(this,"view");y(this,"loading");y(this,"status");y(this,"stage");y(this,"picker");y(this,"applied",0);y(this,"sent",0);y(this,"liveStatus");y(this,"viewport");y(this,"stopListening");y(this,"realSensors");y(this,"controls",{getBrightness:50,getLoudness:0,getPitch:0,getRoll:0});y(this,"pressTimers",new Map);y(this,"check");y(this,"checking",!1);y(this,"onWorldChange");this.world=new _s(e),this.element=document.createElement("section"),this.element.className="visubot",this.element.innerHTML=`

${p("web_visubot_world")}

${p("web_visubot_world_in_preview")}

${vN()}${yN()}`,this.stage=this.element.querySelector(".visubot-stage"),this.picker=this.element.querySelector(".visubot-worlds"),this.status=this.element.querySelector(".visubot-status"),this.liveStatus=this.element.querySelector(".visubot-live"),this.viewport=this.element.querySelector(".visubot-viewport"),this.stopListening=be.listen(()=>this.updateLive()),this.setupControls(),this.check=this.element.querySelector(".visubot-check"),this.setupCheck(),this.updateLive(),this.updateStatus()}show(){this.loading??(this.loading=ee(async()=>{const{Robot3D:e}=await import("./robot3d-Dz8gQ3hd.js");return{Robot3D:e}},[],import.meta.url).then(({Robot3D:e})=>{this.view=new e(this.stage),this.view.setWorld(this.world.setup),this.view.place(this.world.pose,this.world.trail),this.view.setLeds(this.world.leds)}).catch(()=>{this.stage.textContent=p("web_visubot_no_3d")}))}restoreViewport(){this.viewport.parentElement!==this.element&&this.liveStatus.after(this.viewport)}setWorlds(e){this.picker.replaceChildren(),this.picker.hidden=e.length<2,e.forEach((t,n)=>{const a=document.createElement("button");a.textContent=p("web_visubot_world_fmt",n+1),a.addEventListener("click",()=>this.useWorld(t,a)),this.picker.append(a)}),this.useWorld(e[0]??Mi,this.picker.firstElementChild)}useWorld(e,t){var n,a,s,r,o;for(const l of this.picker.children)l.classList.toggle("active",l===t);e!==this.world.setup&&(this.world=new _s(e),this.applied=0,this.sent=0,(n=this.view)==null||n.setWorld(e),(a=this.view)==null||a.place(this.world.pose,this.world.trail),(s=this.view)==null||s.setLed(void 0),(r=this.view)==null||r.setScreen(void 0),this.updateStatus(),(o=this.onWorldChange)==null||o.call(this))}reset(){var e,t,n;this.world.reset(),this.applied=0,this.sent=0,this.realSensors=void 0,(e=this.view)==null||e.place(this.world.pose,this.world.trail),(t=this.view)==null||t.setLed(void 0),(n=this.view)==null||n.setScreen(void 0),this.updateStatus()}prepare(e){e.robotSensors={...this.controls,...this.world.sensors()}}setupControls(){for(const e of this.element.querySelectorAll(".visubot-controls input[type=range]")){const t=e.parentElement.querySelector("output"),n=()=>{this.controls[e.name]=Number(e.value),t.textContent=e.value};e.addEventListener("input",n),n()}for(const e of this.element.querySelectorAll(".visubot-controls button[name]"))e.addEventListener("click",()=>{const t=e.name;this.controls[t]=!0,e.classList.add("pressed"),window.clearTimeout(this.pressTimers.get(t)),this.pressTimers.set(t,window.setTimeout(()=>{this.controls[t]=!1,e.classList.remove("pressed")},1e3))})}setupCheck(){for(const e of this.check.querySelectorAll("button[data-py]"))e.addEventListener("click",()=>{const{after:t,wait:n}=e.dataset;be.run(e.dataset.py).then(()=>t?new Promise(a=>setTimeout(a,Number(n))).then(()=>be.run(t)):void 0).catch(a=>this.liveFailed(a))});this.check.addEventListener("toggle",()=>void this.readCheck())}async readCheck(){if(!this.checking){this.checking=!0;try{for(;this.check.open&&be.connected;){for(const e of this.check.querySelectorAll("[data-sensor]")){if(!this.check.open||!be.connected)break;const t=e.dataset.sensor,n=await be.ask(Pt[t].python).catch(()=>{});n!==void 0&&(e.textContent=typeof Pt[t].simulated=="boolean"?n===!0||typeof n=="number"&&n!==0?"✓":"–":String(typeof n=="number"?Math.round(n*10)/10:n))}await new Promise(e=>setTimeout(e,200))}}finally{this.checking=!1}}}get live(){return be.connected}async prepareLive(e,t=[]){const n={};for(const a of new Set(["getDistance","getLine",...t])){const s=await be.ask(Pt[a].python);typeof Pt[a].simulated=="boolean"?n[a]=s===!0||typeof s=="number"&&s!==0:typeof Pt[a].simulated=="string"?n[a]=typeof s=="string"?s:String(Pt[a].simulated):n[a]=typeof s=="number"?a==="getDistance"?Math.round(s):s:0}this.realSensors=n,e.robotSensors={...this.controls,...this.world.sensors(),...n}}async drive(e){for(;this.sentsetTimeout(n,t.args[0]))}}liveFailed(e){be.disconnect(e instanceof Error?e.message:String(e))}updateLive(){this.liveStatus.textContent=ep(),this.liveStatus.classList.toggle("connected",be.connected),this.check.hidden=!be.connected,be.connected||(this.check.open=!1),this.updateStatus()}follow(e,t){var a,s,r,o;for(;this.appliedl!==0);this.world.tick(z0),n&&((o=this.view)==null||o.moveTo(this.world.pose,this.world.trail,t)),this.updateStatus()}dispose(){var e;this.stopListening();for(const t of this.pressTimers.values())window.clearTimeout(t);(e=this.view)==null||e.dispose(),this.view=void 0,this.loading=void 0}updateStatus(){const e=this.world.lineState().toString(2).padStart(4,"0"),t=[`${p("web_visubot_distance")}: ${this.world.distance()} cm`,`${p("web_visubot_line")}: ${e}`];this.world.bumps>0&&t.push(`⚠︎ ${p("web_visubot_bumps")}: ${this.world.bumps}`),this.world.screen!==void 0&&t.push(`📺 ${this.world.screen}`),this.realSensors&&be.connected&&t.push(`🤖 ${p("web_visubot_distance")}: ${this.realSensors.getDistance} cm · ${p("web_visubot_line")}: ${Number(this.realSensors.getLine).toString(2).padStart(4,"0")}`),this.status.textContent=t.join(" · ")}}let ni;function Kg(i,e){try{ni??(ni=new AudioContext);const t=ni.createOscillator(),n=ni.createGain();t.type="square",t.frequency.value=Math.max(20,Math.min(2e4,i)),n.gain.value=.05,t.connect(n).connect(ni.destination);const a=ni.currentTime+Math.min(Math.max(e,0),5e3)/1e3;t.start(),t.stop(a)}catch{}}function vN(){const i=(t,n,a,s,r)=>``,e=(t,n,a)=>``;return`
🎛 ${p("web_visubot_controls")} + ${Zm(p(t))}`}class xN{constructor(e=Mi){y(this,"element");y(this,"world");y(this,"view");y(this,"loading");y(this,"status");y(this,"stage");y(this,"picker");y(this,"applied",0);y(this,"sent",0);y(this,"liveStatus");y(this,"viewport");y(this,"stopListening");y(this,"realSensors");y(this,"controls",{getBrightness:50,getLoudness:0,getPitch:0,getRoll:0});y(this,"pressTimers",new Map);y(this,"check");y(this,"checking",!1);y(this,"onWorldChange");this.world=new _s(e),this.element=document.createElement("section"),this.element.className="visubot",this.element.innerHTML=`

${p("web_visubot_world")}

${p("web_visubot_world_in_preview")}

${vN()}${yN()}`,this.stage=this.element.querySelector(".visubot-stage"),this.picker=this.element.querySelector(".visubot-worlds"),this.status=this.element.querySelector(".visubot-status"),this.liveStatus=this.element.querySelector(".visubot-live"),this.viewport=this.element.querySelector(".visubot-viewport"),this.stopListening=be.listen(()=>this.updateLive()),this.setupControls(),this.check=this.element.querySelector(".visubot-check"),this.setupCheck(),this.updateLive(),this.updateStatus()}show(){this.loading??(this.loading=ee(async()=>{const{Robot3D:e}=await import("./robot3d-ClismEE4.js");return{Robot3D:e}},[],import.meta.url).then(({Robot3D:e})=>{this.view=new e(this.stage),this.view.setWorld(this.world.setup),this.view.place(this.world.pose,this.world.trail),this.view.setLeds(this.world.leds)}).catch(()=>{this.stage.textContent=p("web_visubot_no_3d")}))}restoreViewport(){this.viewport.parentElement!==this.element&&this.liveStatus.after(this.viewport)}setWorlds(e){this.picker.replaceChildren(),this.picker.hidden=e.length<2,e.forEach((t,n)=>{const a=document.createElement("button");a.textContent=p("web_visubot_world_fmt",n+1),a.addEventListener("click",()=>this.useWorld(t,a)),this.picker.append(a)}),this.useWorld(e[0]??Mi,this.picker.firstElementChild)}useWorld(e,t){var n,a,s,r,o;for(const l of this.picker.children)l.classList.toggle("active",l===t);e!==this.world.setup&&(this.world=new _s(e),this.applied=0,this.sent=0,(n=this.view)==null||n.setWorld(e),(a=this.view)==null||a.place(this.world.pose,this.world.trail),(s=this.view)==null||s.setLed(void 0),(r=this.view)==null||r.setScreen(void 0),this.updateStatus(),(o=this.onWorldChange)==null||o.call(this))}reset(){var e,t,n;this.world.reset(),this.applied=0,this.sent=0,this.realSensors=void 0,(e=this.view)==null||e.place(this.world.pose,this.world.trail),(t=this.view)==null||t.setLed(void 0),(n=this.view)==null||n.setScreen(void 0),this.updateStatus()}prepare(e){e.robotSensors={...this.controls,...this.world.sensors()}}setupControls(){for(const e of this.element.querySelectorAll(".visubot-controls input[type=range]")){const t=e.parentElement.querySelector("output"),n=()=>{this.controls[e.name]=Number(e.value),t.textContent=e.value};e.addEventListener("input",n),n()}for(const e of this.element.querySelectorAll(".visubot-controls button[name]"))e.addEventListener("click",()=>{const t=e.name;this.controls[t]=!0,e.classList.add("pressed"),window.clearTimeout(this.pressTimers.get(t)),this.pressTimers.set(t,window.setTimeout(()=>{this.controls[t]=!1,e.classList.remove("pressed")},1e3))})}setupCheck(){for(const e of this.check.querySelectorAll("button[data-py]"))e.addEventListener("click",()=>{const{after:t,wait:n}=e.dataset;be.run(e.dataset.py).then(()=>t?new Promise(a=>setTimeout(a,Number(n))).then(()=>be.run(t)):void 0).catch(a=>this.liveFailed(a))});this.check.addEventListener("toggle",()=>void this.readCheck())}async readCheck(){if(!this.checking){this.checking=!0;try{for(;this.check.open&&be.connected;){for(const e of this.check.querySelectorAll("[data-sensor]")){if(!this.check.open||!be.connected)break;const t=e.dataset.sensor,n=await be.ask(Pt[t].python).catch(()=>{});n!==void 0&&(e.textContent=typeof Pt[t].simulated=="boolean"?n===!0||typeof n=="number"&&n!==0?"✓":"–":String(typeof n=="number"?Math.round(n*10)/10:n))}await new Promise(e=>setTimeout(e,200))}}finally{this.checking=!1}}}get live(){return be.connected}async prepareLive(e,t=[]){const n={};for(const a of new Set(["getDistance","getLine",...t])){const s=await be.ask(Pt[a].python);typeof Pt[a].simulated=="boolean"?n[a]=s===!0||typeof s=="number"&&s!==0:typeof Pt[a].simulated=="string"?n[a]=typeof s=="string"?s:String(Pt[a].simulated):n[a]=typeof s=="number"?a==="getDistance"?Math.round(s):s:0}this.realSensors=n,e.robotSensors={...this.controls,...this.world.sensors(),...n}}async drive(e){for(;this.sentsetTimeout(n,t.args[0]))}}liveFailed(e){be.disconnect(e instanceof Error?e.message:String(e))}updateLive(){this.liveStatus.textContent=ep(),this.liveStatus.classList.toggle("connected",be.connected),this.check.hidden=!be.connected,be.connected||(this.check.open=!1),this.updateStatus()}follow(e,t){var a,s,r,o;for(;this.appliedl!==0);this.world.tick(z0),n&&((o=this.view)==null||o.moveTo(this.world.pose,this.world.trail,t)),this.updateStatus()}dispose(){var e;this.stopListening();for(const t of this.pressTimers.values())window.clearTimeout(t);(e=this.view)==null||e.dispose(),this.view=void 0,this.loading=void 0}updateStatus(){const e=this.world.lineState().toString(2).padStart(4,"0"),t=[`${p("web_visubot_distance")}: ${this.world.distance()} cm`,`${p("web_visubot_line")}: ${e}`];this.world.bumps>0&&t.push(`⚠︎ ${p("web_visubot_bumps")}: ${this.world.bumps}`),this.world.screen!==void 0&&t.push(`📺 ${this.world.screen}`),this.realSensors&&be.connected&&t.push(`🤖 ${p("web_visubot_distance")}: ${this.realSensors.getDistance} cm · ${p("web_visubot_line")}: ${Number(this.realSensors.getLine).toString(2).padStart(4,"0")}`),this.status.textContent=t.join(" · ")}}let ni;function Kg(i,e){try{ni??(ni=new AudioContext);const t=ni.createOscillator(),n=ni.createGain();t.type="square",t.frequency.value=Math.max(20,Math.min(2e4,i)),n.gain.value=.05,t.connect(n).connect(ni.destination);const a=ni.currentTime+Math.min(Math.max(e,0),5e3)/1e3;t.start(),t.stop(a)}catch{}}function vN(){const i=(t,n,a,s,r)=>``,e=(t,n,a)=>``;return`
🎛 ${p("web_visubot_controls")}

${p("web_visubot_controls_hint")}

${i("getBrightness","web_visubot_sensor_brightness",0,100,50)} ${i("getLoudness","web_visubot_sensor_loudness",0,100,0)} @@ -76522,7 +76573,7 @@ ${i}

${In(p("web_visubot_preview_hint"))}

-

`;const e=t=>this.element.querySelector(t);this.heightBar=e(".robotpreview-height"),this.stage=e(".robotpreview-stage"),this.status=e(".robotpreview-status"),this.picker=e(".visubot-worlds"),this.playButton=e(".robotpreview-play"),this.stackButton=e(".robotpreview-stack"),this.playButton.addEventListener("click",()=>this.playTimer===void 0?this.play():this.stopPlaying(!0)),this.stackButton.addEventListener("click",()=>this.onToggleStacked()),e(".learn-hide").addEventListener("click",()=>this.onHide()),this.rail=document.createElement("button"),this.rail.className="learn-rail robotpreview-rail",this.setStacked(!1),this.relabel()}hostSimulation(e){var t;e!==this.simulation&&((t=this.simulation)==null||t.remove(),this.simulation=e,this.element.classList.toggle("simulation",!!e),e&&(this.pause(),this.status.after(e)),this.relabel())}relabel(){const e=a=>this.element.querySelector(a),t=!!this.simulation;e("h2").textContent=`🤖 ${p(t?"web_visubot_preview_sim_title":"web_visubot_preview_title")}`,e(".hint").textContent=p(t?"web_visubot_preview_sim_hint":"web_visubot_preview_hint"),this.heightBar.title=p("web_visubot_preview_resize");const n=e(".learn-hide");n.title=p("web_visubot_preview_hide"),n.setAttribute("aria-label",p("web_visubot_preview_hide")),this.rail.title=p("web_visubot_preview_show"),this.rail.innerHTML=`${At}🤖 ${In(p("web_visubot_preview_title"))}`,this.setStacked(this.stackButton.textContent==="▥"),this.stopPlaying(!1),this.worldsKey=void 0,this.lastKey=void 0}setStacked(e){const t=e?"web_visubot_preview_side":"web_visubot_preview_stack";this.stackButton.innerHTML=e?"▥":"⬓",this.stackButton.className="icon robotpreview-stack",this.stackButton.dataset.tip=p(t),this.stackButton.setAttribute("aria-label",p(t))}show(){this.loading??(this.loading=ee(async()=>{const{Robot3D:e}=await import("./robot3d-Dz8gQ3hd.js");return{Robot3D:e}},[],import.meta.url).then(({Robot3D:e})=>{var t;this.view=new e(this.stage),this.view.setWorld(this.setup),this.showFrame((t=this.result)==null?void 0:t.frames.at(-1))}).catch(()=>{this.stage.textContent=p("web_visubot_no_3d")}))}update(e,t,n,a,s){if(this.simulation)return;this.show(),a!==this.worldsKey&&(this.worldsKey=a,this.setWorlds(n)),this.input={doc:e,resolve:t};const r=JSON.stringify(s)+` +

`;const e=t=>this.element.querySelector(t);this.heightBar=e(".robotpreview-height"),this.stage=e(".robotpreview-stage"),this.status=e(".robotpreview-status"),this.picker=e(".visubot-worlds"),this.playButton=e(".robotpreview-play"),this.stackButton=e(".robotpreview-stack"),this.playButton.addEventListener("click",()=>this.playTimer===void 0?this.play():this.stopPlaying(!0)),this.stackButton.addEventListener("click",()=>this.onToggleStacked()),e(".learn-hide").addEventListener("click",()=>this.onHide()),this.rail=document.createElement("button"),this.rail.className="learn-rail robotpreview-rail",this.setStacked(!1),this.relabel()}hostSimulation(e){var t;e!==this.simulation&&((t=this.simulation)==null||t.remove(),this.simulation=e,this.element.classList.toggle("simulation",!!e),e&&(this.pause(),this.status.after(e)),this.relabel())}relabel(){const e=a=>this.element.querySelector(a),t=!!this.simulation;e("h2").textContent=`🤖 ${p(t?"web_visubot_preview_sim_title":"web_visubot_preview_title")}`,e(".hint").textContent=p(t?"web_visubot_preview_sim_hint":"web_visubot_preview_hint"),this.heightBar.title=p("web_visubot_preview_resize");const n=e(".learn-hide");n.title=p("web_visubot_preview_hide"),n.setAttribute("aria-label",p("web_visubot_preview_hide")),this.rail.title=p("web_visubot_preview_show"),this.rail.innerHTML=`${At}🤖 ${In(p("web_visubot_preview_title"))}`,this.setStacked(this.stackButton.textContent==="▥"),this.stopPlaying(!1),this.worldsKey=void 0,this.lastKey=void 0}setStacked(e){const t=e?"web_visubot_preview_side":"web_visubot_preview_stack";this.stackButton.innerHTML=e?"▥":"⬓",this.stackButton.className="icon robotpreview-stack",this.stackButton.dataset.tip=p(t),this.stackButton.setAttribute("aria-label",p(t))}show(){this.loading??(this.loading=ee(async()=>{const{Robot3D:e}=await import("./robot3d-ClismEE4.js");return{Robot3D:e}},[],import.meta.url).then(({Robot3D:e})=>{var t;this.view=new e(this.stage),this.view.setWorld(this.setup),this.showFrame((t=this.result)==null?void 0:t.frames.at(-1))}).catch(()=>{this.stage.textContent=p("web_visubot_no_3d")}))}update(e,t,n,a,s){if(this.simulation)return;this.show(),a!==this.worldsKey&&(this.worldsKey=a,this.setWorlds(n)),this.input={doc:e,resolve:t};const r=JSON.stringify(s)+` `+JSON.stringify(e);r!==this.lastKey&&(this.lastKey=r,window.clearTimeout(this.pending),this.pending=window.setTimeout(()=>this.recompute(),120))}setWorlds(e){this.worlds=e,this.picker.replaceChildren(),this.picker.hidden=e.length<2,e.forEach((t,n)=>{const a=document.createElement("button");a.textContent=p("web_visubot_world_fmt",n+1),a.addEventListener("click",()=>this.useWorld(t)),this.picker.append(a)}),this.useWorld(e[0]??Mi)}useWorld(e){var t;this.worlds.forEach((n,a)=>{var s;return(s=this.picker.children[a])==null?void 0:s.classList.toggle("active",n===e)}),!(e===this.setup&&this.result)&&(this.setup=e,(t=this.view)==null||t.setWorld(e),this.recompute())}recompute(){var e;if(this.pending=void 0,this.stopPlaying(!1),!!this.input){try{this.result=Sg(this.input.doc,this.input.resolve,this.setup)}catch{this.result=void 0}this.showFrame((e=this.result)==null?void 0:e.frames.at(-1)),this.updateStatus()}}showFrame(e,t=0){if(!this.view)return;const n=e??{pose:{...this.setup.start},trail:[{x:this.setup.start.x,y:this.setup.start.y}],leds:Array(5).fill(void 0),screen:void 0};t>0?this.view.moveTo(n.pose,n.trail,t):this.view.place(n.pose,n.trail),this.view.setLeds(n.leds),this.view.setScreen(n.screen)}play(){var a;const e=(a=this.result)==null?void 0:a.frames;if(!e||e.length<2||!this.view)return;this.stopPlaying(!1);let t=0;this.showFrame(e[0]),this.playButton.innerHTML=me.stop,this.playButton.dataset.tip=p("web_visubot_preview_stop"),this.playButton.setAttribute("aria-label",p("web_visubot_preview_stop"));const n=()=>{if(t++,t>=e.length){this.stopPlaying(!1);return}const s=e[t];s.tone&&Kg(s.tone[0],s.tone[1]),this.showFrame(s,vo-30),this.playTimer=window.setTimeout(n,vo)};this.playTimer=window.setTimeout(n,vo)}stopPlaying(e){var t;this.playTimer!==void 0&&window.clearTimeout(this.playTimer),this.playTimer=void 0,this.playButton.innerHTML=me.play,this.playButton.dataset.tip=p("web_visubot_preview_play"),this.playButton.setAttribute("aria-label",p("web_visubot_preview_play")),e&&this.showFrame((t=this.result)==null?void 0:t.frames.at(-1))}updateStatus(){const e=this.result;if(this.playButton.disabled=!e||e.frames.length<2,!e){this.status.textContent="";return}const t=[p("web_visubot_preview_distance_fmt",e.distance)];e.bumps>0&&t.push(`⚠︎ ${p("web_visubot_bumps")}: ${e.bumps}`),e.stop==="input"?t.push(p("web_visubot_preview_input")):e.stop==="limit"?t.push(p("web_visubot_preview_limit")):e.stop==="error"&&e.notice&&t.push(`⚠︎ ${i1(e.notice)}`),this.status.textContent=t.join(" · ")}pause(){window.clearTimeout(this.pending),this.pending=void 0,this.lastKey=void 0,this.stopPlaying(!1)}}const $q={left:12,top:10},Xq=8,ir=8e3,Ai=16,yo=12,E2="#fafafa";function N2(i){const e=i.caption.trim();return e===""?p("diagram_title_placeholder"):e}function Pd(i){let e=i.trim().replace(/\.visustruct$/i,"");if(e==="")return"";for(e=e.replace(/\s/g,"-").replace(/[/:\\*?"<>|]/g,"-");e.includes("--");)e=e.replace(/--/g,"-");return e=e.replace(/^-+|-+$/g,""),e.length>120&&(e=e.slice(0,120).replace(/^-+|-+$/g,"")),e}function Dd(i,e){return Pd(i.caption)||Pd(e)||"VisuStruct"}function Kq(i,e,t){const n=i.split(/\s+/),a=[];let s="";for(const r of n){const o=s?`${s} ${r}`:r;s&&t(o,Ai,"bold")>e?(a.push(s),s=r):s=o}if(s&&a.push(s),a.length>2){let r=a.slice(1).join(" ");for(;r.length>1&&t(r+"…",Ai,"bold")>e;)r=r.slice(0,-1);return[a[0],r+"…"]}return a}function Od(i,e,t,n=320){const a={...i,elements:i.elements.map(ds)},s=new bh(e,t).layout(a,$q),r=Math.min(ir,Math.max(n,s.canvasSize.width)),o=Math.min(ir,Math.max(n,s.canvasSize.height));if(r<=2||o<=2)return;const l=Kq(N2(i),r-2*yo,t),u=Math.ceil(Ai*1.2),m=Math.min(56,l.length*u+2),c=m+o,d=new wh(e,t).render(s,{width:r,height:o},void 0,Xq);d.setAttribute("y",String(m)),d.removeAttribute("class");const h=Te("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:c,viewBox:`0 0 ${r} ${c}`});h.append(Te("rect",{x:0,y:0,width:r,height:c,fill:E2}));const g=Te("text",{x:yo,y:0,"font-family":ar,"font-size":Ai,"font-weight":600,fill:"black"});return l.forEach((f,b)=>{const x=Te("tspan",{x:yo,y:b*u+Ai});x.textContent=f,g.append(x)}),h.append(g,d),{svg:h,width:r,height:c}}function F2(i){return` `+new XMLSerializer().serializeToString(i.svg)}async function Bd(i,e){const t=Math.max(1,Math.min(e,ir/i.width,ir/i.height)),n=URL.createObjectURL(new Blob([F2(i)],{type:"image/svg+xml"}));try{const a=new Image;a.src=n,await a.decode();const s=document.createElement("canvas");s.width=Math.round(i.width*t),s.height=Math.round(i.height*t);const r=s.getContext("2d");return r.fillStyle=E2,r.fillRect(0,0,s.width,s.height),r.drawImage(a,0,0,s.width,s.height),s}finally{URL.revokeObjectURL(n)}}function eQ(i){return new Promise((e,t)=>i.toBlob(n=>n?e(n):t(new Error("PNG konnte nicht erzeugt werden.")),"image/png"))}function tQ(i,e){const a=Math.max(1,i),s=Math.max(1,e),r=f=>{const b=f.width-64,x=f.height-64;return{s:Math.min(b/a,x/s)*.98,cw:b,ch:x}},o={width:595,height:842},l={width:842,height:595},u=r(o),m=r(l),[c,d]=m.s>u.s?[l,m]:[o,u],h=a*d.s,g=s*d.s;return{page:c,draw:{x:32+(d.cw-h)/2,y:32+(d.ch-g)/2,width:h,height:g}}}async function nQ(i){const e=new Blob([i]).stream().pipeThrough(new CompressionStream("deflate"));return new Uint8Array(await new Response(e).arrayBuffer())}function Md(i){let e="FEFF";for(let t=0;t`}async function iQ(i,e,t,n,a){const{page:s,draw:r}=tQ(n.width,n.height),o=await nQ(i),l=x=>(Math.round(x*100)/100).toString(),u=`q ${l(r.width)} 0 0 ${l(r.height)} ${l(r.x)} ${l(s.height-r.y-r.height)} cm /Im0 Do Q`,m=new TextEncoder,c=[["<< /Type /Catalog /Pages 2 0 R >>"],["<< /Type /Pages /Kids [3 0 R] /Count 1 >>"],[`<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${s.width} ${s.height}] /Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>`],[`<< /Type /XObject /Subtype /Image /Width ${e} /Height ${t} /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /FlateDecode /Length ${o.length} >> stream @@ -76744,7 +76795,7 @@ ${c}
- ${W(p("web_about_version_fmt").replace("%@","0.14.33"))} + ${W(p("web_about_version_fmt").replace("%@","0.14.34"))}
@@ -76816,7 +76867,7 @@ ${c}

VisuStruct ${W(p("web_brand_suffix"))}

-

${W(p("web_about_version_fmt").replace("%@","0.14.33"))}

+

${W(p("web_about_version_fmt").replace("%@","0.14.34"))}

Holger Sebastiao

${e("about_web_label","https://visustruct.visucode.de","visustruct.visucode.de")} ${e("about_developer_label","https://www.sebastiao.org","www.sebastiao.org")} @@ -76838,4 +76889,4 @@ ${c}

${W(p("close_unsaved_title"))}

${W(p("web_discard_message_fmt",this.fileName))}

-
`,t.addEventListener("click",n=>{const a=n.target.dataset.r;a===void 0&&n.target!==t||(t.remove(),e(a==="1"))}),document.body.append(t),t.querySelector('[data-r="0"]').focus()}):Promise.resolve(!0)}showMessage(e){this.statusLine.textContent=e,this.statusLine.classList.add("message"),setTimeout(()=>{this.statusLine.classList.remove("message"),this.updateStatus()},6e3)}loadXML(e,t,n){let a;try{a=n0(e)}catch(s){this.showMessage(p("web_err_unreadable_fmt",t,s.message));return}(this.dirty||this.tab.fileName||this.tab.exerciseId)&&this.addTab(),this.doc=a,this.tab.fileName=t.replace(/\.(strk|xml)$/i,".visustruct"),this.fileHandle=n&&/\.visustruct$/i.test(t)?n:void 0,this.resetHistory()}async open(e){const t=window;if(!t.showOpenFilePicker||this.inViewer)return e.click();try{const[n]=await t.showOpenFilePicker({types:Ed()}),a=await n.getFile();this.loadXML(await a.text(),a.name,n)}catch{}}async save(){var n,a;if(!this.downloads&&await this.saveToWorkspace())return;const e=new Blob([d1(this.doc)],{type:"application/xml"}),t=window;try{if(this.downloads){const s=this.fileName+".txt";await this.downloads.save({filename:s,data:e}),(n=this.tab).fileName??(n.fileName=this.fileName),this.dirty=!1,this.render(),this.showMessage(p("web_saved_txt_fmt",s));return}if(!this.fileHandle&&t.showSaveFilePicker&&!this.inViewer&&(this.fileHandle=await t.showSaveFilePicker({suggestedName:this.fileName,types:Ed()}),this.tab.fileName=this.fileHandle.name),this.fileHandle){const s=await this.fileHandle.createWritable();await s.write(e),await s.close()}else{const s=document.createElement("a");s.href=URL.createObjectURL(e),s.download=this.fileName,s.click(),setTimeout(()=>URL.revokeObjectURL(s.href),1e3)}(a=this.tab).fileName??(a.fileName=this.fileName),this.dirty=!1,this.render()}catch{}}async exportDiagram(e){if(e==="visustruct"){const s=Dd(this.doc,hn(this.tab));return this.offerDownload(`${s}.visustruct`,new Blob([d1(this.doc)],{type:"application/xml"}))}const t=Od(this.doc,this.metrics,this.measure);if(!t){this.showMessage(p(e==="print"?"err_diagram_too_small_print":"err_diagram_too_small_export"));return}const n=Dd(this.doc,hn(this.tab)),a=Math.max(2,window.devicePixelRatio||1)*this.zoom;try{switch(e){case"svg":{t.svg.setAttribute("width",String(t.width*this.zoom)),t.svg.setAttribute("height",String(t.height*this.zoom)),await this.offerDownload(`${n}.svg`,new Blob([F2(t)],{type:"image/svg+xml"}));break}case"png":{const s=await Bd(t,a);await this.offerDownload(`${n}.png`,await eQ(s));break}case"pdf":{const s=await Bd(t,Math.max(a,3)),r=await iQ(aQ(s),s.width,s.height,t,N2(this.doc));await this.offerDownload(`${n}.pdf`,r);break}case"print":this.printDiagram(t);break}}catch(s){this.showMessage(p("web_export_failed_fmt",s instanceof Error?s.message:String(s)))}}printDiagram(e){const t=document.createElement("div");t.className="print-sheet",e.svg.removeAttribute("width"),e.svg.removeAttribute("height"),t.append(e.svg),document.body.append(t);const n=()=>t.remove();window.addEventListener("afterprint",n,{once:!0});try{window.print()}catch{n(),this.showMessage(`${p("err_print_unavailable")} ${p("web_print_hint")}`);return}setTimeout(n,6e4)}async offerDownload(e,t){try{if(this.downloads){try{await this.downloads.save({filename:e,data:t}),this.showMessage(p("web_saved_fmt",e))}catch{await this.downloads.save({filename:e+".txt",data:t}),this.showMessage(p("web_saved_txt_fmt",e+".txt"))}return}const n=document.createElement("a");n.href=URL.createObjectURL(t),n.download=e,n.click(),setTimeout(()=>URL.revokeObjectURL(n.href),1e3)}catch{this.showMessage(p("err_save_failed_fmt",e))}}setupFileDrop(){window.addEventListener("dragover",e=>{var t;(t=e.dataTransfer)!=null&&t.types.includes("Files")&&(e.preventDefault(),this.root.classList.add("file-drag"))}),window.addEventListener("dragleave",e=>{e.relatedTarget===null&&this.root.classList.remove("file-drag")}),window.addEventListener("drop",async e=>{var n;this.root.classList.remove("file-drag");const t=(n=e.dataTransfer)==null?void 0:n.files[0];t&&(e.preventDefault(),this.loadXML(await t.text(),t.name))})}onKeyDown(e){var a,s;const t=e.metaKey||e.ctrlKey,n=e.target instanceof HTMLTextAreaElement||e.target instanceof HTMLInputElement||((a=e.target)==null?void 0:a.isContentEditable)===!0;if(t&&e.key.toLowerCase()==="s")e.preventDefault(),this.save();else if(t&&e.key.toLowerCase()==="p")e.preventDefault(),this.simulating||this.exportDiagram("print");else if(t&&e.key.toLowerCase()==="o")e.preventDefault(),this.open(this.root.querySelector("input[type=file]"));else{if(n||this.simulating)return;t&&e.key.toLowerCase()==="z"?(e.preventDefault(),e.shiftKey?this.redo():this.undo()):t&&e.key.toLowerCase()==="c"&&!((s=getSelection())!=null&&s.toString())?this.copySelection()&&e.preventDefault():t&&e.key.toLowerCase()==="x"?(e.preventDefault(),this.cutSelection()):t&&e.key.toLowerCase()==="v"?(e.preventDefault(),this.paste()):t&&e.key.toLowerCase()==="y"?(e.preventDefault(),this.redo()):e.key==="F2"&&this.selected?(e.preventDefault(),this.renameVariable(this.selected)):e.key==="Delete"||e.key==="Backspace"?(e.preventDefault(),this.deleteSelection()):e.key==="Escape"&&(this.drag?this.endDrag():(this.selected=void 0,this.render()))}}svgPoint(e,t){if(!this.svg)return;const n=this.svg.getBoundingClientRect(),a=e-n.left,s=t-n.top;if(!(a<0||s<0||a>n.width||s>n.height))return{x:a/this.zoom,y:s/this.zoom}}nodeAt(e,t){for(let n=this.flat.length-1;n>=0;n--){const a=this.flat[n].frame;if(e>=a.x&&e<=a.x+a.width&&t>=a.y&&t<=a.y+a.height)return this.flat[n]}}onCanvasPointerDown(e){if(this.simulating)return;const t=this.svgPoint(e.clientX,e.clientY);if(!t)return;document.activeElement instanceof HTMLElement&&document.activeElement.blur();const n=this.nodeAt(t.x,t.y),a=n&&this.selected&&Do(n.idPath,this.selected);this.selected=n==null?void 0:n.idPath,this.render(),n&&e.pointerType!=="touch"&&!(Sn(this.doc,n.idPath)&&!a)&&this.beginDrag(e,{kind:"move",path:n.idPath})}beginDrag(e,t){e.button!==0||this.simulating||(e.preventDefault(),this.drag={source:t,pointerId:e.pointerId,startX:e.clientX,startY:e.clientY,active:!1})}onPointerMove(e){const t=this.drag;if(!t||e.pointerId!==t.pointerId)return;if(!t.active){if(Math.hypot(e.clientX-t.startX,e.clientY-t.startY)<5)return;t.active=!0,t.ghost=this.makeGhost(t.source),document.body.append(t.ghost),this.root.classList.add("dragging")}t.ghost.style.transform=`translate(${e.clientX+12}px, ${e.clientY+12}px)`,this.autoScroll(e.clientX,e.clientY);const n=this.svgPoint(e.clientX,e.clientY);t.target=n?this.dropTargetAt(n.x,n.y,t.source):void 0,this.showDropTarget(t.target)}onPointerUp(e){const t=this.drag;!t||e.pointerId!==t.pointerId||(t.active&&t.target?this.applyDrop(t.source,t.target):!t.active&&t.source.kind==="palette"?this.insertNearSelection(t.source.make()):!t.active&&t.source.kind==="sensor"&&this.insertSensor(t.source.text),this.endDrag())}endDrag(){var e,t;(t=(e=this.drag)==null?void 0:e.ghost)==null||t.remove(),this.drag=void 0,this.root.classList.remove("dragging"),this.showDropTarget(void 0)}makeGhost(e){const t=document.createElement("div");if(t.className="drag-ghost",e.kind==="palette"||e.kind==="sensor")t.textContent=e.label;else{const n=Bt(this.doc,e.path);t.textContent=`${wo(n.type)}: ${$l(n)[0]}`}return t}autoScroll(e,t){const n=this.canvasHost.getBoundingClientRect(),a=40,s=12;t>n.bottom-a&&tn.top-a&&(this.canvasHost.scrollTop-=s),e>n.right-a&&en.left-a&&(this.canvasHost.scrollLeft-=s)}dropTargetAt(e,t,n){var l;const a=((l=this.layout)==null?void 0:l.elements)??[],s=this.nodeAt(e,t);if(n.kind==="sensor")return!s||Sn(this.doc,s.idPath)?void 0:Wd.includes(Bt(this.doc,s.idPath).type)?{kind:"condition",path:s.idPath,frame:s.frame}:void 0;if(!s){const u=a[a.length-1];if(!u)return;const m=u.frame.y+u.frame.height;return t>m?n.kind==="move"&&n.path.length===1&&n.path[0]===a.length-1?void 0:{kind:"rootAppend",frame:{x:u.frame.x,y:m,width:u.frame.width,height:0}}:t=n.path.length&&n.path.every((u,m)=>r[m]===u)?void 0:Sn(this.doc,r)?{kind:"replace",path:r,frame:s.frame}:{kind:t"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e])}function sh(i){if(!i)return[];for(const e of[...zt.flatMap(t=>t.steps.flatMap(n=>n.blocks)),...Pn.flatMap(t=>t.blocks)])if(!(e.kind!=="exercise"||e.exercise.id!==i))return e.exercise.tests.flatMap(t=>{const n=t.world?ts(t.world):void 0;return n?[n]:[]});return[]}let Jt,Ql,Ul;function rh(i){const e=i.dataset.tip;if(!e)return;Jt??(Jt=Object.assign(document.createElement("div"),{className:"tooltip",role:"tooltip"})),Jt.isConnected||document.body.append(Jt),Jt.textContent=e,Jt.hidden=!1;const t=i.getBoundingClientRect(),n=Jt.offsetWidth,a=Jt.offsetHeight,s=Math.min(Math.max(8,t.left+t.width/2-n/2),window.innerWidth-n-8),r=t.bottom+6+a{if(i.pointerType==="touch")return;const e=i.target.closest("[data-tip]");e!==Ul&&(So(),e&&(Ul=e,Ql=window.setTimeout(()=>rh(e),350)))}),document.addEventListener("focusin",i=>{const e=i.target.closest("[data-tip]");So(),e!=null&&e.matches(":focus-visible")&&rh(e)});for(const i of["pointerdown","focusout","scroll","keydown"])document.addEventListener(i,So,!0)}const Yl="visustruct.reloadedAfterError";function H2(){try{const i=Number(sessionStorage.getItem(Yl));if(i&&Date.now()-i<3e4)return!1;sessionStorage.setItem(Yl,String(Date.now()))}catch{return!1}return location.reload(),!0}function TQ(i){console.error(i);const e=(navigator.language||"").toLowerCase().startsWith("de"),t=document.createElement("div");t.className="startup-error";const n=document.createElement("h1");n.textContent=e?"VisuStruct konnte nicht starten":"VisuStruct could not start";const a=document.createElement("p");a.textContent=e?"Wahrscheinlich gibt es gerade eine neue Version. Lade die Seite neu. Hilft das nicht, drücke Strg+Umschalt+R (Mac: ⌘⇧R).":"There is probably a new version. Reload the page. If that does not help, press Ctrl+Shift+R (Mac: ⌘⇧R).";const s=document.createElement("button");s.textContent=e?"Neu laden":"Reload",s.addEventListener("click",()=>location.reload());const r=document.createElement("pre");r.textContent=String(i instanceof Error?i.message:i),t.append(n,a,s,r),(document.getElementById("app")??document.body).replaceWith(t)}window.addEventListener("vite:preloadError",i=>{H2()&&i.preventDefault()});const _Q=L3();Promise.all([Ch(_Q,!1),jh(M3(),!1)]).then(()=>{G2(),SQ();const i=new URLSearchParams(location.search);if(!["visustruct","visubot","visuobject","visuflow"].some(a=>i.has(a))&&!Xg()){const a=lh();a==="visubot"?ns("on"):a==="visuobject"&&tl()}i.has("visuobject")&&tl(),i.has("visuflow")&&$g();const t=document.getElementById("app"),n=!i.has("visustruct")&&!i.has("visubot");if(Ug()&&n)return ee(async()=>{const{ObjectApp:a}=await import("./objectApp-wBFGa9mb.js").then(s=>s.g);return{ObjectApp:a}},[],import.meta.url).then(({ObjectApp:a})=>void new a(t));if(Yg()&&n)return ee(async()=>{const{FlowApp:a}=await import("./flowApp-C8yZ_A03.js");return{FlowApp:a}},[],import.meta.url).then(({FlowApp:a})=>void new a(t));new zQ(t)}).then(()=>{try{sessionStorage.removeItem(Yl)}catch{}}).catch(i=>{/dynamically imported module|Importing a module script failed|error loading dynamically/i.test(String(i))&&H2()||TQ(i)});export{Yn as C,Iq as J,Mx as L,ee as _,uq as a,Dq as b,P2 as c,OQ as d,$g as e,ns as f,yQ as g,wa as h,me as i,_N as j,TN as k,a3 as l,DQ as m,o1 as n,tl as o,_q as p,Pd as q,Em as r,NW as s,p as t,F2 as u,Bd as v,nl as w,eQ as x,iQ as y,aQ as z}; + `,t.addEventListener("click",n=>{const a=n.target.dataset.r;a===void 0&&n.target!==t||(t.remove(),e(a==="1"))}),document.body.append(t),t.querySelector('[data-r="0"]').focus()}):Promise.resolve(!0)}showMessage(e){this.statusLine.textContent=e,this.statusLine.classList.add("message"),setTimeout(()=>{this.statusLine.classList.remove("message"),this.updateStatus()},6e3)}loadXML(e,t,n){let a;try{a=n0(e)}catch(s){this.showMessage(p("web_err_unreadable_fmt",t,s.message));return}(this.dirty||this.tab.fileName||this.tab.exerciseId)&&this.addTab(),this.doc=a,this.tab.fileName=t.replace(/\.(strk|xml)$/i,".visustruct"),this.fileHandle=n&&/\.visustruct$/i.test(t)?n:void 0,this.resetHistory()}async open(e){const t=window;if(!t.showOpenFilePicker||this.inViewer)return e.click();try{const[n]=await t.showOpenFilePicker({types:Ed()}),a=await n.getFile();this.loadXML(await a.text(),a.name,n)}catch{}}async save(){var n,a;if(!this.downloads&&await this.saveToWorkspace())return;const e=new Blob([d1(this.doc)],{type:"application/xml"}),t=window;try{if(this.downloads){const s=this.fileName+".txt";await this.downloads.save({filename:s,data:e}),(n=this.tab).fileName??(n.fileName=this.fileName),this.dirty=!1,this.render(),this.showMessage(p("web_saved_txt_fmt",s));return}if(!this.fileHandle&&t.showSaveFilePicker&&!this.inViewer&&(this.fileHandle=await t.showSaveFilePicker({suggestedName:this.fileName,types:Ed()}),this.tab.fileName=this.fileHandle.name),this.fileHandle){const s=await this.fileHandle.createWritable();await s.write(e),await s.close()}else{const s=document.createElement("a");s.href=URL.createObjectURL(e),s.download=this.fileName,s.click(),setTimeout(()=>URL.revokeObjectURL(s.href),1e3)}(a=this.tab).fileName??(a.fileName=this.fileName),this.dirty=!1,this.render()}catch{}}async exportDiagram(e){if(e==="visustruct"){const s=Dd(this.doc,hn(this.tab));return this.offerDownload(`${s}.visustruct`,new Blob([d1(this.doc)],{type:"application/xml"}))}const t=Od(this.doc,this.metrics,this.measure);if(!t){this.showMessage(p(e==="print"?"err_diagram_too_small_print":"err_diagram_too_small_export"));return}const n=Dd(this.doc,hn(this.tab)),a=Math.max(2,window.devicePixelRatio||1)*this.zoom;try{switch(e){case"svg":{t.svg.setAttribute("width",String(t.width*this.zoom)),t.svg.setAttribute("height",String(t.height*this.zoom)),await this.offerDownload(`${n}.svg`,new Blob([F2(t)],{type:"image/svg+xml"}));break}case"png":{const s=await Bd(t,a);await this.offerDownload(`${n}.png`,await eQ(s));break}case"pdf":{const s=await Bd(t,Math.max(a,3)),r=await iQ(aQ(s),s.width,s.height,t,N2(this.doc));await this.offerDownload(`${n}.pdf`,r);break}case"print":this.printDiagram(t);break}}catch(s){this.showMessage(p("web_export_failed_fmt",s instanceof Error?s.message:String(s)))}}printDiagram(e){const t=document.createElement("div");t.className="print-sheet",e.svg.removeAttribute("width"),e.svg.removeAttribute("height"),t.append(e.svg),document.body.append(t);const n=()=>t.remove();window.addEventListener("afterprint",n,{once:!0});try{window.print()}catch{n(),this.showMessage(`${p("err_print_unavailable")} ${p("web_print_hint")}`);return}setTimeout(n,6e4)}async offerDownload(e,t){try{if(this.downloads){try{await this.downloads.save({filename:e,data:t}),this.showMessage(p("web_saved_fmt",e))}catch{await this.downloads.save({filename:e+".txt",data:t}),this.showMessage(p("web_saved_txt_fmt",e+".txt"))}return}const n=document.createElement("a");n.href=URL.createObjectURL(t),n.download=e,n.click(),setTimeout(()=>URL.revokeObjectURL(n.href),1e3)}catch{this.showMessage(p("err_save_failed_fmt",e))}}setupFileDrop(){window.addEventListener("dragover",e=>{var t;(t=e.dataTransfer)!=null&&t.types.includes("Files")&&(e.preventDefault(),this.root.classList.add("file-drag"))}),window.addEventListener("dragleave",e=>{e.relatedTarget===null&&this.root.classList.remove("file-drag")}),window.addEventListener("drop",async e=>{var n;this.root.classList.remove("file-drag");const t=(n=e.dataTransfer)==null?void 0:n.files[0];t&&(e.preventDefault(),this.loadXML(await t.text(),t.name))})}onKeyDown(e){var a,s;const t=e.metaKey||e.ctrlKey,n=e.target instanceof HTMLTextAreaElement||e.target instanceof HTMLInputElement||((a=e.target)==null?void 0:a.isContentEditable)===!0;if(t&&e.key.toLowerCase()==="s")e.preventDefault(),this.save();else if(t&&e.key.toLowerCase()==="p")e.preventDefault(),this.simulating||this.exportDiagram("print");else if(t&&e.key.toLowerCase()==="o")e.preventDefault(),this.open(this.root.querySelector("input[type=file]"));else{if(n||this.simulating)return;t&&e.key.toLowerCase()==="z"?(e.preventDefault(),e.shiftKey?this.redo():this.undo()):t&&e.key.toLowerCase()==="c"&&!((s=getSelection())!=null&&s.toString())?this.copySelection()&&e.preventDefault():t&&e.key.toLowerCase()==="x"?(e.preventDefault(),this.cutSelection()):t&&e.key.toLowerCase()==="v"?(e.preventDefault(),this.paste()):t&&e.key.toLowerCase()==="y"?(e.preventDefault(),this.redo()):e.key==="F2"&&this.selected?(e.preventDefault(),this.renameVariable(this.selected)):e.key==="Delete"||e.key==="Backspace"?(e.preventDefault(),this.deleteSelection()):e.key==="Escape"&&(this.drag?this.endDrag():(this.selected=void 0,this.render()))}}svgPoint(e,t){if(!this.svg)return;const n=this.svg.getBoundingClientRect(),a=e-n.left,s=t-n.top;if(!(a<0||s<0||a>n.width||s>n.height))return{x:a/this.zoom,y:s/this.zoom}}nodeAt(e,t){for(let n=this.flat.length-1;n>=0;n--){const a=this.flat[n].frame;if(e>=a.x&&e<=a.x+a.width&&t>=a.y&&t<=a.y+a.height)return this.flat[n]}}onCanvasPointerDown(e){if(this.simulating)return;const t=this.svgPoint(e.clientX,e.clientY);if(!t)return;document.activeElement instanceof HTMLElement&&document.activeElement.blur();const n=this.nodeAt(t.x,t.y),a=n&&this.selected&&Do(n.idPath,this.selected);this.selected=n==null?void 0:n.idPath,this.render(),n&&e.pointerType!=="touch"&&!(Sn(this.doc,n.idPath)&&!a)&&this.beginDrag(e,{kind:"move",path:n.idPath})}beginDrag(e,t){e.button!==0||this.simulating||(e.preventDefault(),this.drag={source:t,pointerId:e.pointerId,startX:e.clientX,startY:e.clientY,active:!1})}onPointerMove(e){const t=this.drag;if(!t||e.pointerId!==t.pointerId)return;if(!t.active){if(Math.hypot(e.clientX-t.startX,e.clientY-t.startY)<5)return;t.active=!0,t.ghost=this.makeGhost(t.source),document.body.append(t.ghost),this.root.classList.add("dragging")}t.ghost.style.transform=`translate(${e.clientX+12}px, ${e.clientY+12}px)`,this.autoScroll(e.clientX,e.clientY);const n=this.svgPoint(e.clientX,e.clientY);t.target=n?this.dropTargetAt(n.x,n.y,t.source):void 0,this.showDropTarget(t.target)}onPointerUp(e){const t=this.drag;!t||e.pointerId!==t.pointerId||(t.active&&t.target?this.applyDrop(t.source,t.target):!t.active&&t.source.kind==="palette"?this.insertNearSelection(t.source.make()):!t.active&&t.source.kind==="sensor"&&this.insertSensor(t.source.text),this.endDrag())}endDrag(){var e,t;(t=(e=this.drag)==null?void 0:e.ghost)==null||t.remove(),this.drag=void 0,this.root.classList.remove("dragging"),this.showDropTarget(void 0)}makeGhost(e){const t=document.createElement("div");if(t.className="drag-ghost",e.kind==="palette"||e.kind==="sensor")t.textContent=e.label;else{const n=Bt(this.doc,e.path);t.textContent=`${wo(n.type)}: ${$l(n)[0]}`}return t}autoScroll(e,t){const n=this.canvasHost.getBoundingClientRect(),a=40,s=12;t>n.bottom-a&&tn.top-a&&(this.canvasHost.scrollTop-=s),e>n.right-a&&en.left-a&&(this.canvasHost.scrollLeft-=s)}dropTargetAt(e,t,n){var l;const a=((l=this.layout)==null?void 0:l.elements)??[],s=this.nodeAt(e,t);if(n.kind==="sensor")return!s||Sn(this.doc,s.idPath)?void 0:Wd.includes(Bt(this.doc,s.idPath).type)?{kind:"condition",path:s.idPath,frame:s.frame}:void 0;if(!s){const u=a[a.length-1];if(!u)return;const m=u.frame.y+u.frame.height;return t>m?n.kind==="move"&&n.path.length===1&&n.path[0]===a.length-1?void 0:{kind:"rootAppend",frame:{x:u.frame.x,y:m,width:u.frame.width,height:0}}:t=n.path.length&&n.path.every((u,m)=>r[m]===u)?void 0:Sn(this.doc,r)?{kind:"replace",path:r,frame:s.frame}:{kind:t"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e])}function sh(i){if(!i)return[];for(const e of[...zt.flatMap(t=>t.steps.flatMap(n=>n.blocks)),...Pn.flatMap(t=>t.blocks)])if(!(e.kind!=="exercise"||e.exercise.id!==i))return e.exercise.tests.flatMap(t=>{const n=t.world?ts(t.world):void 0;return n?[n]:[]});return[]}let Jt,Ql,Ul;function rh(i){const e=i.dataset.tip;if(!e)return;Jt??(Jt=Object.assign(document.createElement("div"),{className:"tooltip",role:"tooltip"})),Jt.isConnected||document.body.append(Jt),Jt.textContent=e,Jt.hidden=!1;const t=i.getBoundingClientRect(),n=Jt.offsetWidth,a=Jt.offsetHeight,s=Math.min(Math.max(8,t.left+t.width/2-n/2),window.innerWidth-n-8),r=t.bottom+6+a{if(i.pointerType==="touch")return;const e=i.target.closest("[data-tip]");e!==Ul&&(So(),e&&(Ul=e,Ql=window.setTimeout(()=>rh(e),350)))}),document.addEventListener("focusin",i=>{const e=i.target.closest("[data-tip]");So(),e!=null&&e.matches(":focus-visible")&&rh(e)});for(const i of["pointerdown","focusout","scroll","keydown"])document.addEventListener(i,So,!0)}const Yl="visustruct.reloadedAfterError";function H2(){try{const i=Number(sessionStorage.getItem(Yl));if(i&&Date.now()-i<3e4)return!1;sessionStorage.setItem(Yl,String(Date.now()))}catch{return!1}return location.reload(),!0}function TQ(i){console.error(i);const e=(navigator.language||"").toLowerCase().startsWith("de"),t=document.createElement("div");t.className="startup-error";const n=document.createElement("h1");n.textContent=e?"VisuStruct konnte nicht starten":"VisuStruct could not start";const a=document.createElement("p");a.textContent=e?"Wahrscheinlich gibt es gerade eine neue Version. Lade die Seite neu. Hilft das nicht, drücke Strg+Umschalt+R (Mac: ⌘⇧R).":"There is probably a new version. Reload the page. If that does not help, press Ctrl+Shift+R (Mac: ⌘⇧R).";const s=document.createElement("button");s.textContent=e?"Neu laden":"Reload",s.addEventListener("click",()=>location.reload());const r=document.createElement("pre");r.textContent=String(i instanceof Error?i.message:i),t.append(n,a,s,r),(document.getElementById("app")??document.body).replaceWith(t)}window.addEventListener("vite:preloadError",i=>{H2()&&i.preventDefault()});const _Q=L3();Promise.all([Ch(_Q,!1),jh(M3(),!1)]).then(()=>{G2(),SQ();const i=new URLSearchParams(location.search);if(!["visustruct","visubot","visuobject","visuflow"].some(a=>i.has(a))&&!Xg()){const a=lh();a==="visubot"?ns("on"):a==="visuobject"&&tl()}i.has("visuobject")&&tl(),i.has("visuflow")&&$g();const t=document.getElementById("app"),n=!i.has("visustruct")&&!i.has("visubot");if(Ug()&&n)return ee(async()=>{const{ObjectApp:a}=await import("./objectApp-JyBNWSS3.js").then(s=>s.g);return{ObjectApp:a}},[],import.meta.url).then(({ObjectApp:a})=>void new a(t));if(Yg()&&n)return ee(async()=>{const{FlowApp:a}=await import("./flowApp-D9O9LuF5.js");return{FlowApp:a}},[],import.meta.url).then(({FlowApp:a})=>void new a(t));new zQ(t)}).then(()=>{try{sessionStorage.removeItem(Yl)}catch{}}).catch(i=>{/dynamically imported module|Importing a module script failed|error loading dynamically/i.test(String(i))&&H2()||TQ(i)});export{Yn as C,Iq as J,Mx as L,ee as _,uq as a,Dq as b,P2 as c,OQ as d,$g as e,ns as f,yQ as g,wa as h,me as i,_N as j,TN as k,a3 as l,DQ as m,o1 as n,tl as o,_q as p,Pd as q,Em as r,NW as s,p as t,F2 as u,Bd as v,nl as w,eQ as x,iQ as y,aQ as z}; diff --git a/website/app/assets/objectApp-wBFGa9mb.js b/website/app/assets/objectApp-JyBNWSS3.js similarity index 99% rename from website/app/assets/objectApp-wBFGa9mb.js rename to website/app/assets/objectApp-JyBNWSS3.js index 4b86e64c..f8efe801 100644 --- a/website/app/assets/objectApp-wBFGa9mb.js +++ b/website/app/assets/objectApp-JyBNWSS3.js @@ -1,5 +1,5 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./projectZip-DuO6aDli.js","./index-BJMBJyRW.js","./index-C2teIEHU.css"])))=>i.map(i=>d[i]); -var Ns=Object.defineProperty;var Os=(a,e,t)=>e in a?Ns(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t;var E=(a,e,t)=>Os(a,typeof e!="symbol"?e+"":e,t);import{t as d,i as ie,s as Ps,m as Is,g as Ds,w as Rs,J as Hs,c as Bs,a as Ws,b as Ye,p as zs,d as Vs,e as Us,f as Js,_ as wt,h as $t,j as Ks,r as _t,k as Xs,l as Ys,n as ct}from"./index-BJMBJyRW.js";function Gs(a){const e=[];let t=0;for(;ti.map(i=>d[i]); +var Ns=Object.defineProperty;var Os=(a,e,t)=>e in a?Ns(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t;var E=(a,e,t)=>Os(a,typeof e!="symbol"?e+"":e,t);import{t as d,i as ie,s as Ps,m as Is,g as Ds,w as Rs,J as Hs,c as Bs,a as Ws,b as Ye,p as zs,d as Vs,e as Us,f as Js,_ as wt,h as $t,j as Ks,r as _t,k as Xs,l as Ys,n as ct}from"./index-xN_dxLEc.js";function Gs(a){const e=[];let t=0;for(;te.text===","?", ":e.text).join("")}function ms(a){const e=[[]];let t=0;for(const s of a)s.text==="<"||s.text==="("||s.text==="["||s.text==="{"?t++:(s.text===">"||s.text===")"||s.text==="]"||s.text==="}")&&t--,s.text===","&&t===0?e.push([]):e[e.length-1].push(s);return e.filter(s=>s.length>0)}function ft(a){var t,s;const e=[];for(let i=0;i{const t=ft(e).filter(i=>i.text!=="final"),s=t[t.length-1];return{name:s!=null&&s.word?s.text:"",type:lt(t.slice(0,-1))}})}function kt(a,e,t,s){var x,L;const i=ft(a),n=new Set;let o=0;for(;o"));const r=i.slice(o);if(r.length===0||a.length===0)return[];const c=a[0].from,l=r.findIndex(S=>S.text==="("),h=r.findIndex(S=>S.text==="="),u=l>0&&(h<0||lS.text==="="),y=_<0?g:g.slice(0,_);let w=y.length-1;for(;w>0&&!y[w].word;)w--;if(w<1)return[];const $=lt(y.slice(0,w)),p=m.length>1,v=[];return m.forEach((S,k)=>{var C;const j=S.findIndex(F=>F.text==="="),M=j<0?S:S.slice(0,j),A=k===0?y[w]:M.find(F=>F.word);if(!A)return;const R=M.filter(F=>F.from>A.from&&F.text==="[").length;v.push({kind:"field",name:A.text,type:$+"[]".repeat(R),params:[],visibility:xt(n,f),isStatic:n.has("static"),isAbstract:!1,from:c,to:s,headerFrom:c,headerTo:k===0?((C=M[M.length-1])==null?void 0:C.to)??A.to:A.to,shared:p,nameFrom:A.from,nameTo:A.to})}),v}function Qs(a,e,t){var n;let s=[],i=e;for(;ih.text==="="),c=ye(a,i,"{","}");if(r){s.push(...a.slice(i,c)),i=c;continue}const l=s.map(h=>h.text);l.includes("class")||l.includes("interface")||l.includes("enum")||s.length>0&&t.members.push(...kt(s,t.name,t.kind==="interface",((n=a[c-1])==null?void 0:n.to)??o.to)),s=[],i=c;continue}s.push(o),i++}return t.bodyEnd=a.length>0?a[a.length-1].to:0,i}function oe(a){var n,o,r,c;const e=Gs(a),t=[];let s=[],i=0;for(;iw.text==="class"||w.text==="interface"),f=u>=0?h[u+1]:void 0;if(!(f!=null&&f.word)){i=ye(e,i,"{","}"),s=[];continue}let m=u;for(;m>0&&(fs.has(h[m-1].text)||h[m-1].text==="@");)m--;const g={name:f.text,kind:h[u].text==="interface"?"interface":"class",isAbstract:h.slice(m,u).some(w=>w.text==="abstract"),interfaces:[],members:[],from:((n=s[s.indexOf(h[m])])==null?void 0:n.from)??h[m].from,to:0,headerFrom:((o=s[s.indexOf(h[m])])==null?void 0:o.from)??h[m].from,headerTo:h[h.length-1].to,nameFrom:f.from,nameTo:f.to,bodyEnd:0};let _=u+2;((r=h[_])==null?void 0:r.text)==="<"&&(_=ye(h,_,"<",">"));let y="";for(;_")-1:w.word&&y==="extends"&&g.kind==="class"?g.superclass??(g.superclass=w.text):w.word&&y&&g.interfaces.push(w.text)}i=Qs(e,i+1,g),g.to=((c=e[i-1])==null?void 0:c.to)??a.length,t.push(g),s=[]}return t}function Fe(a){const e=/^([\p{L}_$][\p{L}\p{N}_$]*)(\[\])+$/u.exec(a);if(e)return{name:e[1],many:!0};const t=/^(?:ArrayList|LinkedList|List|Set|HashSet|TreeSet|Collection|Queue|Deque|ArrayDeque|Stack|Vector)<([\p{L}_$][\p{L}\p{N}_$]*)>$/u.exec(a);return t?{name:t[1],many:!0}:{name:a,many:!1}}function ei(a){const e=new Set(a.map(s=>s.name)),t=[];for(const s of a){s.superclass&&e.has(s.superclass)&&t.push({kind:"extends",from:s.name,to:s.superclass});for(const i of s.interfaces)e.has(i)&&t.push({kind:s.kind==="interface"?"extends":"implements",from:s.name,to:i});for(const i of s.members){if(i.kind!=="field")continue;const n=Fe(i.type);e.has(n.name)&&t.push({kind:"association",from:s.name,to:n.name,role:i.name,multiplicity:n.many?"0..*":"1"})}}return t}function Ge(a){const e=a.params.map(t=>`${t.name}: ${t.type}`).join(", ");return a.kind==="field"?`${a.visibility} ${a.name}: ${a.type}`:a.kind==="constructor"?`${a.visibility} ${a.name}(${e})`:`${a.visibility} ${a.name}(${e}): ${a.type}`}const ti=/^[\p{L}_$][\p{L}\p{N}_$]*$/u;function Ve(a){var c;let e=a.trim().replace(/;$/,"").trim();if(!e)return;let t;/^[+\-#~]/.test(e)&&(t=e[0],e=e.slice(1).trim());let s=!1;const i=e.split(/\s+/);for(;["static","public","private","protected"].includes(i[0]);){const l=i.shift();l==="static"?s=!0:t??(t=l==="public"?"+":l==="private"?"-":"#")}e=i.join(" ");const n=e.indexOf("(");if(n>=0){const l=e.lastIndexOf(")");if(lg.trim()).filter(Boolean).map(g=>{const _=/^([\p{L}_$][\p{L}\p{N}_$]*)\s*:\s*(.+)$/u.exec(g);if(_)return{name:_[1],type:_[2].replace(/\s+/g,"")};const y=/^(.+)\s+([\p{L}_$][\p{L}\p{N}_$]*)$/u.exec(g);return y?{name:y[2],type:y[1].replace(/\s+/g,"")}:{name:g,type:"int"}});return{kind:"method",visibility:t,name:h,type:u==null?void 0:u.replace(/\s+/g,""),params:m,isStatic:s}}const o=/^([\p{L}_$][\p{L}\p{N}_$]*)\s*(?::\s*(.+))?$/u.exec(e);if(o)return{kind:"field",visibility:t,name:o[1],type:(c=o[2])==null?void 0:c.replace(/\s+/g,""),params:[],isStatic:s};const r=/^(.+?)\s+([\p{L}_$][\p{L}\p{N}_$]*)$/u.exec(e);if(r)return{kind:"field",visibility:t,name:r[2],type:r[1].replace(/\s+/g,""),params:[],isStatic:s}}const si={"+":"public ","-":"private ","#":"protected ","~":""};function ii(a){return/^(int|long|short|byte)$/.test(a)?"0":/^(double|float)$/.test(a)?"0.0":a==="boolean"?"false":a==="char"?"' '":"null"}function bs(a,e,t){const s=e.kind==="interface",i=s?"":si[a.visibility??(a.kind==="field"?"-":"+")],n=a.isStatic?"static ":"";if(a.kind==="field")return`${i}${n}${a.type??"int"} ${a.name}`;const o=a.params.map(r=>`${r.type} ${r.name}`).join(", ");return a.name===e.name?`${i}${a.name}(${o})`:`${i}${n}${t&&!s?"abstract ":""}${a.type??"void"} ${a.name}(${o})`}const Ue=(a,e)=>a.lastIndexOf(` `,e-1)+1;function mt(a,e,t){const s=Ue(a,e),i=a.slice(s,e);let n=t;for(;n
- ${b(d("web_about_version_fmt").replace("%@","0.14.33"))} + ${b(d("web_about_version_fmt").replace("%@","0.14.34"))}
@@ -315,7 +315,7 @@ public String toString() { `,"in"),this.consolePane().input.hidden=!0,t.vm.input(e),this.debugRun())}debugError(e){var o;const t=e.pos?String(e.pos.line+1):"",s=((o=e.pos)==null?void 0:o.file.split("/").pop())??"",i=e.detail.replace(/^expected:/,""),n={syntax:"web_visuobject_dbg_err_syntax",symbol:"web_visuobject_dbg_err_symbol",unsupported:"web_visuobject_dbg_err_unsupported",nomain:"web_visuobject_no_main",type:"web_visuobject_dbg_err_type",import:"web_visuobject_dbg_err_import",typename:"web_visuobject_dbg_err_typename"}[e.code];e.pos&&this.showLine(e.pos.file,e.pos.line),this.stopDebug(),this.debugStatus(d(n,s,t,i),!0)}showDebugButtons(){const e=this.dbg,t=(e==null?void 0:e.state)==="paused";for(const s of this.shell.querySelectorAll("[data-dbg]"))s.disabled=!e||(s.dataset.dbg==="pause"?e.state!=="running":!t)}showLine(e,t){this.project.files.some(s=>s.path===e)&&e!==this.active&&this.openFile(e),this.editor.setMarks({placeholders:[],problems:[],current:t},!0)}showDebugState(){const e=this.dbg;if(!e)return;e.frames=e.vm.stack();const t=e.vm.heap(),s=e.frames[e.frame];s&&this.showLine(s.pos.file,s.pos.line);const i=e.values.size===0&&e.vars.size===0,n=new Set,o=new Map;for(const h of t)for(const u of h.fields){const f=`dbg${h.id}.${u.name}`;o.set(f,u.value),!i&&e.values.get(f)!==u.value&&n.add(f)}e.values=o;const r=new Set,c=new Map;e.frames.forEach((h,u)=>{for(const f of h.vars){const m=`${e.frames.length-u}|${h.title}|${f.name}`;c.set(m,f.value),!i&&e.vars.get(m)!==f.value&&r.add(`${h.title}|${f.name}`)}}),e.vars=c;const l={objects:this.liveObjects(t),changed:n,frames:e.frames,frame:e.frame,changedVars:r,onFrame:h=>{e.frame=h,l.frame=h;const u=e.frames[h];u&&this.showLine(u.pos.file,u.pos.line),this.objectDiagram.renderInspector()},move:(h,u)=>e.places.set(h,u)};this.objectDiagram.live=l,this.sequence=e.vm.sequence(),this.diagramMode==="object"&&this.objectDiagram.render(),this.diagramMode==="sequence"&&this.renderSequence()}renderSequence(){var n,o,r;const e=this.shell.querySelector(".vo-seqcanvas"),t=e.querySelector(".vo-seq"),s=e.querySelector(".vo-empty"),i=this.sequence;if(s.hidden=!!i&&i.events.length>0,s.textContent=d(i?"web_visuobject_seq_no_calls":"web_visuobject_seq_empty"),!i||!i.events.length)t.innerHTML="",t.setAttribute("width","0");else{const c=((n=this.dbg)==null?void 0:n.state)==="paused"||((o=this.dbg)==null?void 0:o.state)==="input",{svg:l,width:h,height:u}=Ai(i,c?i.events.length-1:void 0);t.innerHTML=l+(i.truncated?`${b(d("web_visuobject_seq_truncated"))}`:""),t.setAttribute("width",String(h)),t.setAttribute("height",String(u)),c&&((r=t.querySelector(".vo-seq-msg.current"))==null||r.scrollIntoView({block:"nearest",inline:"nearest"}))}this.renderSequenceInspector()}renderSequenceInspector(){if(this.objectDiagram.live)return this.objectDiagram.renderInspector();this.inspector.innerHTML=`

${b(d("web_visuobject_seq_hint"))}

`}liveObjects(e){const t=this.dbg,s=this.project.objects??[],i=c=>40+c.fields.length*20,n=[],o=[],r=[];for(const c of e){const l=`dbg${c.id}`,h=t.places.get(l)??s.find(u=>u.name===c.name&&u.cls===c.cls);if(!h){r.push(c);continue}t.places.set(l,{x:h.x,y:h.y}),n.push({x:h.x,y:h.y,w:260,h:i(c)})}for(const c of r){const l=i(c);let h={x:24,y:24};e:for(let u=24;u<6e3;u+=30)for(let f=24;f<=24+3*320;f+=320)if(n.every(m=>f+260+30<=m.x||m.x+m.w+30<=f||u+l+30<=m.y||m.y+m.h+30<=u)){h={x:f,y:u};break e}t.places.set(`dbg${c.id}`,h),n.push({...h,w:260,h:l})}for(const c of e){const l=`dbg${c.id}`;o.push({id:l,name:c.name,cls:c.cls,...t.places.get(l),values:Object.fromEntries(c.fields.map(h=>[h.name,h.value]))})}return o}stopDebug(e,t=!1){const s=this.dbg;s&&clearTimeout(s.timer),this.dbg=void 0,s&&(this.sequence=s.vm.sequence()),this.objectDiagram.live=void 0,this.consolePane().input.hidden=!0,this.shell.querySelector(".vo-dbg-controls").hidden=!0,this.shell.querySelector("[data-action=stop]").disabled=!0,this.shell.querySelector("[data-action=run]").disabled=!1,t||this.editor.setMarks({placeholders:[],problems:[]},!1),e&&this.debugStatus(d(e),t),this.diagramMode==="object"&&this.objectDiagram.render(),this.diagramMode==="sequence"&&this.renderSequence()}chooseWorld(e){if(e!=="object"){if(e==="flow"){Us(),location.href=`${location.pathname}?visuflow${location.hash}`;return}Js(e),location.href=`${location.pathname}?${e==="on"?"visubot":"visustruct"}${location.hash}`}}get activeFile(){return this.project.files.find(e=>e.path===this.active)}showActive(){const e=this.activeFile;this.editor.setText((e==null?void 0:e.text)??""),this.editor.setBreakpoints(e?this.breakpoints.get(e.path)??[]:[]),this.editor.setReadOnly(!e),e&&!this.openTabs.includes(e.path)&&this.openTabs.push(e.path),this.renderTabs(),J(ot,this.active??"")}renderTabs(){if(this.openTabs=this.openTabs.filter(e=>this.project.files.some(t=>t.path===e)),J(cs,JSON.stringify(this.openTabs)),this.openTabs.length===0){this.tabs.innerHTML=`${b(d("web_visuobject_no_file"))}`;return}this.tabs.innerHTML=this.openTabs.map(e=>{const t=e===this.active,s=this.isDirty(e);return`
-
`}).join("")}onTabClick(e){var i;const t=e.target,s=(i=t.closest("[data-tab]"))==null?void 0:i.dataset.tab;if(s){if(t.closest("[data-close]"))return this.closeTab(s);this.treeSelection=`file:${s}`,this.openFile(s)}}closeTab(e){const t=this.openTabs.indexOf(e);t<0||(this.openTabs.splice(t,1),e===this.active?(this.active=this.openTabs[Math.min(t,this.openTabs.length-1)],this.lastTyping=0,this.showActive(),this.refresh()):this.renderTabs())}snapshot(){return JSON.stringify({project:this.project,active:this.active})}remember(){this.history.push(this.snapshot()),this.history.length>jn&&this.history.shift(),this.future=[]}setProject(e,t=this.active){var s;this.remember(),this.lastTyping=0,this.project=e,this.active=e.files.some(i=>i.path===t)?t:(s=e.files[0])==null?void 0:s.path,this.showActive(),this.refresh()}openFile(e){if(e===this.active)return;this.active=e,this.lastTyping=0,this.showActive();const t=D(e);this.currentPackage=t,this.open.set(`pkg:${t}`,!0),this.refresh()}typed(){const e=this.activeFile;if(!e)return;const t=Date.now();t-this.lastTyping>1500&&this.remember(),this.lastTyping=t,this.project=$e(this.project,e.path,this.editor.text),this.saveBreakpoints(),this.dbg&&this.stopDebug("web_visuobject_dbg_code_changed"),this.refresh(),clearTimeout(this.renameTimer),this.renameTimer=window.setTimeout(()=>this.syncFileName(),700)}syncFileName(){var c;const e=this.activeFile;if(!e||this.editing)return;const t=Q(e.path).replace(/\.java$/i,""),s=this.classes.filter(l=>l.path===e.path);if(s.length===0||s.some(l=>l.name===t))return;const i=((c=/\bpublic\s+(?:abstract\s+|final\s+)*(?:class|interface|enum)\s+(\w+)/.exec(e.text))==null?void 0:c[1])??s[0].name;if(!pe.test(i)||s.filter(l=>l.name===i).length!==1)return;const n=le(D(e.path),`${i}.java`);if(this.project.files.some(l=>l.path===n))return;let o=Oe(this.project,e.path,n);const r=this.positions.get(t);r&&!this.positions.has(i)&&this.positions.set(i,r);for(const l of Object.keys(o.uml??{}))l.startsWith(`${t}.`)&&(o={...o,uml:ke(o.uml,l,i+l.slice(t.length))});this.openTabs=this.openTabs.map(l=>l===e.path?n:l),this.treeSelection===`file:${e.path}`&&(this.treeSelection=`file:${n}`),this.isOpen(`file:${e.path}`)&&this.open.set(`file:${n}`,!0),this.project=o,this.active=n,J(ot,n),this.savePositions(),this.refresh()}undo(e){const t=e?this.future:this.history,s=e?this.history:this.future,i=t.pop();if(i===void 0)return;s.push(this.snapshot());const n=JSON.parse(i);this.project=n.project,this.active=n.active,this.lastTyping=0,this.showActive(),this.refresh()}refresh(){J(os,Pe(this.project)),this.renderTabs(),this.classes=Ct(this.project),this.selection&&!this.findClass(this.selection.cls)&&(this.selection=void 0),this.relSelection&&!this.findRelation(this.relSelection)&&!this.findDependency(this.relSelection)&&(this.relSelection=void 0),this.editing||(this.render(),this.renderTree())}ownTypesAt(e){const t=this.activeFile;if(!t)return;const s=this.editor.view.state.doc.toString(),i=X(D(t.path)),n=oe(s).map(l=>({...l,pkg:i})),o=new Set(n.map(l=>l.name)),r=n.find(l=>l.headerFrom<=e&&e<=l.bodyEnd),c=ct()==="de"?"de":ct()==="pt-PT"?"pt":"en";return Ki([...n,...this.classes.filter(l=>l.path!==t.path&&!o.has(l.name))],{cls:r==null?void 0:r.name,pkg:i},c)}findClass(e){return this.classes.find(t=>t.name===e)}caretMoved(){var n,o;const e=this.editor.caret,t=this.classes.find(r=>r.path===this.active&&e>=r.from&&e<=r.to),s=t==null?void 0:t.members.findIndex(r=>e>=r.from&&e<=r.to),i=t?{cls:t.name,member:s!==void 0&&s>=0?s:void 0}:void 0;(i==null?void 0:i.cls)===((n=this.selection)==null?void 0:n.cls)&&(i==null?void 0:i.member)===((o=this.selection)==null?void 0:o.member)||(this.selection=i,this.editing||(this.render(),this.renderTree()))}showInCode(e,t){e.path!==this.active&&(this.active=e.path,this.lastTyping=0,this.showActive());const s=this.editor.view,[i,n]=t?[t.headerFrom,t.headerTo]:[e.nameFrom,e.nameTo],o=Math.min(n,s.state.doc.length);s.dispatch({selection:{anchor:Math.min(i,o),head:o},scrollIntoView:!0})}message(e,t=!1){this.status.textContent=e,this.status.classList.toggle("hint",t)}openFiles(){const e=document.createElement("input");e.type="file",e.multiple=!0,e.accept=".zip,.java,.visuobject,application/zip,text/plain",e.addEventListener("change",()=>void this.readFiles([...e.files??[]])),e.click()}async readFiles(e){var t;if(e.length!==0)try{const s=e.find(r=>/\.zip$/i.test(r.name));if(s){const{projectFromZip:r}=await wt(async()=>{const{projectFromZip:l}=await import("./projectZip-DuO6aDli.js");return{projectFromZip:l}},__vite__mapDeps([0,1,2]),import.meta.url),c=r(new Uint8Array(await s.arrayBuffer()),s.name.replace(/\.zip$/i,""));await this.newProject(c);return}const i=e.find(r=>/\.visuobject$/i.test(r.name));if(i){const r=qt(await i.text());if(!r)throw new Error("format");await this.newProject(r);return}const n=At(this.project.name,await Promise.all(e.map(async r=>({name:r.name,text:await r.text()}))));let o=this.project;for(const r of n.files)o=et(o,r.path,r.text);this.setProject(o,(t=n.files[0])==null?void 0:t.path)}catch{this.message(d("web_visuobject_open_failed"))}}async save(){this.workspace?await this.writeCurrent():await this.downloadZip()}async downloadZip(){const{projectToZip:e}=await wt(async()=>{const{projectToZip:s}=await import("./projectZip-DuO6aDli.js");return{projectToZip:s}},__vite__mapDeps([0,1,2]),import.meta.url),t=e(this.project);Ln(`${this.project.name||"Projekt"}.zip`,t.slice().buffer,"application/zip")}isDirty(e){var t;return!this.workspace||this.saved===void 0?!1:e===void 0?this.saved!==Pe(this.project):this.savedFiles.get(e)!==((t=this.project.files.find(s=>s.path===e))==null?void 0:t.text)}markSaved(){this.saved=Pe(this.project),this.savedFiles=new Map(this.project.files.map(e=>[e.path,e.text]))}async restoreWorkspace(){if(!$t())return;const e=await Ks(us);if(e!=null&&e.ready){const t=await _t(e.handle);if(t)return this.useWorkspace(t.root,!0)}this.pendingFolder=e==null?void 0:e.handle,this.renderWorkspace()}async useWorkspace(e,t=!1){var s;this.workspace=e,this.pendingFolder=void 0,J(rt,"0");try{this.projects=await is(e);const i=se(We),n=this.project;if(t&&i&&this.projects.includes(i)){const o={active:this.active,tabs:[...this.openTabs],positions:new Map(this.positions)};await this.loadProject(i),this.positions=o.positions,this.savePositions(),Pe(n)!==this.saved&&(this.project=n),this.openTabs=o.tabs.filter(r=>this.project.files.some(c=>c.path===r)),this.active=this.project.files.some(r=>r.path===o.active)?o.active:(s=this.project.files[0])==null?void 0:s.path,this.showActive(),this.refresh()}else!this.projects.some(o=>o.toLowerCase()===ge(n.name).toLowerCase())&&n.files.length?(this.folder=ge(n.name),await this.writeCurrent(!1)):this.projects.length?await this.loadProject(this.projects.includes(i??"")?i:this.projects[0]):(this.folder=ge(n.name),await this.writeCurrent(!1))}catch(i){this.message(d("web_visuobject_ws_failed",String((i==null?void 0:i.message)??i)))}this.renderWorkspace(),this.refresh()}async loadProject(e){var i;const{project:t,positions:s}=await wn(this.workspace,e);this.folder=e,this.project=t,this.markSaved(),this.message(""),this.history=[],this.future=[],this.lastTyping=0,this.selection=void 0,this.relSelection=void 0,this.treeSelection=void 0,this.currentPackage=void 0,this.positions=new Map(Object.entries(s)),this.savePositions(),this.openTabs=[],this.active=(i=t.files[0])==null?void 0:i.path,J(We,e),this.showActive(),this.refresh()}async writeCurrent(e=!0){const t=this.workspace;if(!t)return!1;const s=ge(this.project.name),i=this.folder,n=new Set(this.classes.map(r=>r.name)),o=Object.fromEntries([...this.positions].filter(([r])=>n.has(r)));if(s!==i&&this.projects.some(r=>r!==i&&r.toLowerCase()===s.toLowerCase()))return this.message(d("web_visuobject_ws_taken",this.project.name)),!1;try{return await xn(t,s,this.project,o),i&&i!==s&&this.projects.includes(i)&&await t.remove(i),this.folder=s,this.projects=await is(t),J(We,s),this.markSaved(),e&&this.message(d("web_visuobject_ws_saved",t.name,s),!0),this.refresh(),!0}catch(r){return this.message(d("web_visuobject_ws_failed",String((r==null?void 0:r.message)??r))),!1}}async switchProject(e){if(!(!this.workspace||e===this.folder)&&!(this.isDirty()&&!await this.writeCurrent(!1)))try{await this.loadProject(e)}catch(t){this.message(d("web_visuobject_ws_failed",String((t==null?void 0:t.message)??t)))}}async newProject(e,t,s=!1){var n,o;if(!this.workspace){this.setProject(e,t??((n=e.files[0])==null?void 0:n.path)),e.files.length===0&&!s&&this.editProjectName();return}if(this.isDirty()&&!await this.writeCurrent(!1))return;const i=ns(ge(e.name),this.projects);this.project={...e,name:i},this.folder=i,this.history=[],this.future=[],this.openTabs=[],this.positions.clear(),this.savePositions(),this.active=e.files.some(r=>r.path===t)?t:(o=e.files[0])==null?void 0:o.path,this.showActive(),this.refresh(),await this.writeCurrent(!1)&&(this.message(d("web_visuobject_ws_created",i),!0),e.files.length===0&&!s&&this.editProjectName())}get currentPlace(){const e=this.currentPackage??(this.active?D(this.active):ce(this.project)[0]??"");return{root:U(e),pkg:X(e)}}async newFromWizard(e){var u;const t=this.currentPlace,s=(f,m)=>{let g=f;for(let _=2;m(g);_++)g=f+_;return g},i=await an(e,{roots:ue(this.project),packagesIn:f=>ce(this.project,f).map(X),classes:this.classes,root:t.root,pkg:t.pkg,suggest:f=>f==="project"?ns(d("web_visuobject_project_name"),this.workspace?[...this.projects,this.folder??""]:[]):f==="folder"?s("test",m=>ue(this.project).includes(m)):f==="package"?s(d("web_visuobject_new_package_name"),m=>ce(this.project).includes(re(t.root,m))):this.uniqueClassName(d(f==="class"?"web_visuobject_new_class_name":"web_visuobject_new_interface_name")),check:(f,m,g,_)=>{if(!m)return d("web_visuobject_new_name_missing");if(f==="project")return this.workspace&&this.projects.some(y=>y!==this.folder&&y.toLowerCase()===ge(m).toLowerCase())?d("web_visuobject_ws_taken",m):void 0;if(f==="folder")return!Je(m)||ue(this.project).includes(m)?d("web_visuobject_bad_folder",m):void 0;if(f==="package")return!Mt(m)||ce(this.project).includes(re(g,m))?d("web_visuobject_bad_package",m):void 0;if(!pe.test(m))return d("web_visuobject_bad_name",m);if(this.findClass(m)||this.project.files.some(y=>y.path===le(re(g,_),`${m}.java`)))return d("web_visuobject_new_exists",m);if(m.charAt(0)!==m.charAt(0).toUpperCase())return d("web_visuobject_new_upper")}});if(!i)return;const{name:n,root:o,pkg:r}=i;if(e==="project")return this.newProject({name:n,files:[],packages:[]},void 0,!0);if(this.message(""),e==="folder")return this.currentPackage=re(n,""),this.treeSelection=`root:${n}`,this.open.set(`root:${n}`,!0),this.setProject(vi(this.project,n));if(e==="package"){const f=re(o,n);return this.currentPackage=f,this.treeSelection=`pkg:${f}`,this.open.set(`root:${o}`,!0),this.setProject(mi(this.project,f))}const c=re(o,r),l=le(c,`${n}.java`);this.currentPackage=c,this.selection={cls:n},this.open.set(`root:${o}`,!0),this.open.set(`pkg:${c}`,!0),this.setProject(et(this.project,l,this.sectioned(nn(i.options),n)),l);const h=this.findClass(n);h&&this.showInCode(h),(u=this.canvas.querySelector(`.uml-class[data-class="${CSS.escape(n)}"]`))==null||u.scrollIntoView({block:"nearest",inline:"nearest"})}editProjectName(){this.treeSelection="project",this.renderTree(),this.startEditing(this.tree.querySelector('[data-node="project"] > .vo-row .vo-label'))}renderWorkspace(){const e=this.wsBox;e.hidden=!$t();const t=this.shell.querySelector("[data-action=save]");if(t.dataset.tip=d(this.workspace?"web_visuobject_save_ws_tip":"web_visuobject_save_tip"),e.hidden)return;const s=(i,n,o="text-button",r)=>``;this.workspace?(e.className="vo-ws",e.innerHTML=`${b(this.workspace.name)} + `}).join("")}onTabClick(e){var i;const t=e.target,s=(i=t.closest("[data-tab]"))==null?void 0:i.dataset.tab;if(s){if(t.closest("[data-close]"))return this.closeTab(s);this.treeSelection=`file:${s}`,this.openFile(s)}}closeTab(e){const t=this.openTabs.indexOf(e);t<0||(this.openTabs.splice(t,1),e===this.active?(this.active=this.openTabs[Math.min(t,this.openTabs.length-1)],this.lastTyping=0,this.showActive(),this.refresh()):this.renderTabs())}snapshot(){return JSON.stringify({project:this.project,active:this.active})}remember(){this.history.push(this.snapshot()),this.history.length>jn&&this.history.shift(),this.future=[]}setProject(e,t=this.active){var s;this.remember(),this.lastTyping=0,this.project=e,this.active=e.files.some(i=>i.path===t)?t:(s=e.files[0])==null?void 0:s.path,this.showActive(),this.refresh()}openFile(e){if(e===this.active)return;this.active=e,this.lastTyping=0,this.showActive();const t=D(e);this.currentPackage=t,this.open.set(`pkg:${t}`,!0),this.refresh()}typed(){const e=this.activeFile;if(!e)return;const t=Date.now();t-this.lastTyping>1500&&this.remember(),this.lastTyping=t,this.project=$e(this.project,e.path,this.editor.text),this.saveBreakpoints(),this.dbg&&this.stopDebug("web_visuobject_dbg_code_changed"),this.refresh(),clearTimeout(this.renameTimer),this.renameTimer=window.setTimeout(()=>this.syncFileName(),700)}syncFileName(){var c;const e=this.activeFile;if(!e||this.editing)return;const t=Q(e.path).replace(/\.java$/i,""),s=this.classes.filter(l=>l.path===e.path);if(s.length===0||s.some(l=>l.name===t))return;const i=((c=/\bpublic\s+(?:abstract\s+|final\s+)*(?:class|interface|enum)\s+(\w+)/.exec(e.text))==null?void 0:c[1])??s[0].name;if(!pe.test(i)||s.filter(l=>l.name===i).length!==1)return;const n=le(D(e.path),`${i}.java`);if(this.project.files.some(l=>l.path===n))return;let o=Oe(this.project,e.path,n);const r=this.positions.get(t);r&&!this.positions.has(i)&&this.positions.set(i,r);for(const l of Object.keys(o.uml??{}))l.startsWith(`${t}.`)&&(o={...o,uml:ke(o.uml,l,i+l.slice(t.length))});this.openTabs=this.openTabs.map(l=>l===e.path?n:l),this.treeSelection===`file:${e.path}`&&(this.treeSelection=`file:${n}`),this.isOpen(`file:${e.path}`)&&this.open.set(`file:${n}`,!0),this.project=o,this.active=n,J(ot,n),this.savePositions(),this.refresh()}undo(e){const t=e?this.future:this.history,s=e?this.history:this.future,i=t.pop();if(i===void 0)return;s.push(this.snapshot());const n=JSON.parse(i);this.project=n.project,this.active=n.active,this.lastTyping=0,this.showActive(),this.refresh()}refresh(){J(os,Pe(this.project)),this.renderTabs(),this.classes=Ct(this.project),this.selection&&!this.findClass(this.selection.cls)&&(this.selection=void 0),this.relSelection&&!this.findRelation(this.relSelection)&&!this.findDependency(this.relSelection)&&(this.relSelection=void 0),this.editing||(this.render(),this.renderTree())}ownTypesAt(e){const t=this.activeFile;if(!t)return;const s=this.editor.view.state.doc.toString(),i=X(D(t.path)),n=oe(s).map(l=>({...l,pkg:i})),o=new Set(n.map(l=>l.name)),r=n.find(l=>l.headerFrom<=e&&e<=l.bodyEnd),c=ct()==="de"?"de":ct()==="pt-PT"?"pt":"en";return Ki([...n,...this.classes.filter(l=>l.path!==t.path&&!o.has(l.name))],{cls:r==null?void 0:r.name,pkg:i},c)}findClass(e){return this.classes.find(t=>t.name===e)}caretMoved(){var n,o;const e=this.editor.caret,t=this.classes.find(r=>r.path===this.active&&e>=r.from&&e<=r.to),s=t==null?void 0:t.members.findIndex(r=>e>=r.from&&e<=r.to),i=t?{cls:t.name,member:s!==void 0&&s>=0?s:void 0}:void 0;(i==null?void 0:i.cls)===((n=this.selection)==null?void 0:n.cls)&&(i==null?void 0:i.member)===((o=this.selection)==null?void 0:o.member)||(this.selection=i,this.editing||(this.render(),this.renderTree()))}showInCode(e,t){e.path!==this.active&&(this.active=e.path,this.lastTyping=0,this.showActive());const s=this.editor.view,[i,n]=t?[t.headerFrom,t.headerTo]:[e.nameFrom,e.nameTo],o=Math.min(n,s.state.doc.length);s.dispatch({selection:{anchor:Math.min(i,o),head:o},scrollIntoView:!0})}message(e,t=!1){this.status.textContent=e,this.status.classList.toggle("hint",t)}openFiles(){const e=document.createElement("input");e.type="file",e.multiple=!0,e.accept=".zip,.java,.visuobject,application/zip,text/plain",e.addEventListener("change",()=>void this.readFiles([...e.files??[]])),e.click()}async readFiles(e){var t;if(e.length!==0)try{const s=e.find(r=>/\.zip$/i.test(r.name));if(s){const{projectFromZip:r}=await wt(async()=>{const{projectFromZip:l}=await import("./projectZip-BzqOppdo.js");return{projectFromZip:l}},__vite__mapDeps([0,1,2]),import.meta.url),c=r(new Uint8Array(await s.arrayBuffer()),s.name.replace(/\.zip$/i,""));await this.newProject(c);return}const i=e.find(r=>/\.visuobject$/i.test(r.name));if(i){const r=qt(await i.text());if(!r)throw new Error("format");await this.newProject(r);return}const n=At(this.project.name,await Promise.all(e.map(async r=>({name:r.name,text:await r.text()}))));let o=this.project;for(const r of n.files)o=et(o,r.path,r.text);this.setProject(o,(t=n.files[0])==null?void 0:t.path)}catch{this.message(d("web_visuobject_open_failed"))}}async save(){this.workspace?await this.writeCurrent():await this.downloadZip()}async downloadZip(){const{projectToZip:e}=await wt(async()=>{const{projectToZip:s}=await import("./projectZip-BzqOppdo.js");return{projectToZip:s}},__vite__mapDeps([0,1,2]),import.meta.url),t=e(this.project);Ln(`${this.project.name||"Projekt"}.zip`,t.slice().buffer,"application/zip")}isDirty(e){var t;return!this.workspace||this.saved===void 0?!1:e===void 0?this.saved!==Pe(this.project):this.savedFiles.get(e)!==((t=this.project.files.find(s=>s.path===e))==null?void 0:t.text)}markSaved(){this.saved=Pe(this.project),this.savedFiles=new Map(this.project.files.map(e=>[e.path,e.text]))}async restoreWorkspace(){if(!$t())return;const e=await Ks(us);if(e!=null&&e.ready){const t=await _t(e.handle);if(t)return this.useWorkspace(t.root,!0)}this.pendingFolder=e==null?void 0:e.handle,this.renderWorkspace()}async useWorkspace(e,t=!1){var s;this.workspace=e,this.pendingFolder=void 0,J(rt,"0");try{this.projects=await is(e);const i=se(We),n=this.project;if(t&&i&&this.projects.includes(i)){const o={active:this.active,tabs:[...this.openTabs],positions:new Map(this.positions)};await this.loadProject(i),this.positions=o.positions,this.savePositions(),Pe(n)!==this.saved&&(this.project=n),this.openTabs=o.tabs.filter(r=>this.project.files.some(c=>c.path===r)),this.active=this.project.files.some(r=>r.path===o.active)?o.active:(s=this.project.files[0])==null?void 0:s.path,this.showActive(),this.refresh()}else!this.projects.some(o=>o.toLowerCase()===ge(n.name).toLowerCase())&&n.files.length?(this.folder=ge(n.name),await this.writeCurrent(!1)):this.projects.length?await this.loadProject(this.projects.includes(i??"")?i:this.projects[0]):(this.folder=ge(n.name),await this.writeCurrent(!1))}catch(i){this.message(d("web_visuobject_ws_failed",String((i==null?void 0:i.message)??i)))}this.renderWorkspace(),this.refresh()}async loadProject(e){var i;const{project:t,positions:s}=await wn(this.workspace,e);this.folder=e,this.project=t,this.markSaved(),this.message(""),this.history=[],this.future=[],this.lastTyping=0,this.selection=void 0,this.relSelection=void 0,this.treeSelection=void 0,this.currentPackage=void 0,this.positions=new Map(Object.entries(s)),this.savePositions(),this.openTabs=[],this.active=(i=t.files[0])==null?void 0:i.path,J(We,e),this.showActive(),this.refresh()}async writeCurrent(e=!0){const t=this.workspace;if(!t)return!1;const s=ge(this.project.name),i=this.folder,n=new Set(this.classes.map(r=>r.name)),o=Object.fromEntries([...this.positions].filter(([r])=>n.has(r)));if(s!==i&&this.projects.some(r=>r!==i&&r.toLowerCase()===s.toLowerCase()))return this.message(d("web_visuobject_ws_taken",this.project.name)),!1;try{return await xn(t,s,this.project,o),i&&i!==s&&this.projects.includes(i)&&await t.remove(i),this.folder=s,this.projects=await is(t),J(We,s),this.markSaved(),e&&this.message(d("web_visuobject_ws_saved",t.name,s),!0),this.refresh(),!0}catch(r){return this.message(d("web_visuobject_ws_failed",String((r==null?void 0:r.message)??r))),!1}}async switchProject(e){if(!(!this.workspace||e===this.folder)&&!(this.isDirty()&&!await this.writeCurrent(!1)))try{await this.loadProject(e)}catch(t){this.message(d("web_visuobject_ws_failed",String((t==null?void 0:t.message)??t)))}}async newProject(e,t,s=!1){var n,o;if(!this.workspace){this.setProject(e,t??((n=e.files[0])==null?void 0:n.path)),e.files.length===0&&!s&&this.editProjectName();return}if(this.isDirty()&&!await this.writeCurrent(!1))return;const i=ns(ge(e.name),this.projects);this.project={...e,name:i},this.folder=i,this.history=[],this.future=[],this.openTabs=[],this.positions.clear(),this.savePositions(),this.active=e.files.some(r=>r.path===t)?t:(o=e.files[0])==null?void 0:o.path,this.showActive(),this.refresh(),await this.writeCurrent(!1)&&(this.message(d("web_visuobject_ws_created",i),!0),e.files.length===0&&!s&&this.editProjectName())}get currentPlace(){const e=this.currentPackage??(this.active?D(this.active):ce(this.project)[0]??"");return{root:U(e),pkg:X(e)}}async newFromWizard(e){var u;const t=this.currentPlace,s=(f,m)=>{let g=f;for(let _=2;m(g);_++)g=f+_;return g},i=await an(e,{roots:ue(this.project),packagesIn:f=>ce(this.project,f).map(X),classes:this.classes,root:t.root,pkg:t.pkg,suggest:f=>f==="project"?ns(d("web_visuobject_project_name"),this.workspace?[...this.projects,this.folder??""]:[]):f==="folder"?s("test",m=>ue(this.project).includes(m)):f==="package"?s(d("web_visuobject_new_package_name"),m=>ce(this.project).includes(re(t.root,m))):this.uniqueClassName(d(f==="class"?"web_visuobject_new_class_name":"web_visuobject_new_interface_name")),check:(f,m,g,_)=>{if(!m)return d("web_visuobject_new_name_missing");if(f==="project")return this.workspace&&this.projects.some(y=>y!==this.folder&&y.toLowerCase()===ge(m).toLowerCase())?d("web_visuobject_ws_taken",m):void 0;if(f==="folder")return!Je(m)||ue(this.project).includes(m)?d("web_visuobject_bad_folder",m):void 0;if(f==="package")return!Mt(m)||ce(this.project).includes(re(g,m))?d("web_visuobject_bad_package",m):void 0;if(!pe.test(m))return d("web_visuobject_bad_name",m);if(this.findClass(m)||this.project.files.some(y=>y.path===le(re(g,_),`${m}.java`)))return d("web_visuobject_new_exists",m);if(m.charAt(0)!==m.charAt(0).toUpperCase())return d("web_visuobject_new_upper")}});if(!i)return;const{name:n,root:o,pkg:r}=i;if(e==="project")return this.newProject({name:n,files:[],packages:[]},void 0,!0);if(this.message(""),e==="folder")return this.currentPackage=re(n,""),this.treeSelection=`root:${n}`,this.open.set(`root:${n}`,!0),this.setProject(vi(this.project,n));if(e==="package"){const f=re(o,n);return this.currentPackage=f,this.treeSelection=`pkg:${f}`,this.open.set(`root:${o}`,!0),this.setProject(mi(this.project,f))}const c=re(o,r),l=le(c,`${n}.java`);this.currentPackage=c,this.selection={cls:n},this.open.set(`root:${o}`,!0),this.open.set(`pkg:${c}`,!0),this.setProject(et(this.project,l,this.sectioned(nn(i.options),n)),l);const h=this.findClass(n);h&&this.showInCode(h),(u=this.canvas.querySelector(`.uml-class[data-class="${CSS.escape(n)}"]`))==null||u.scrollIntoView({block:"nearest",inline:"nearest"})}editProjectName(){this.treeSelection="project",this.renderTree(),this.startEditing(this.tree.querySelector('[data-node="project"] > .vo-row .vo-label'))}renderWorkspace(){const e=this.wsBox;e.hidden=!$t();const t=this.shell.querySelector("[data-action=save]");if(t.dataset.tip=d(this.workspace?"web_visuobject_save_ws_tip":"web_visuobject_save_tip"),e.hidden)return;const s=(i,n,o="text-button",r)=>``;this.workspace?(e.className="vo-ws",e.innerHTML=`${b(this.workspace.name)} ${s("zip",d("web_visuobject_ws_zip"),"text-button",d("web_visuobject_ws_zip_tip"))} ${s("switch",d("web_visuobject_ws_switch"),"text-button")}`):this.pendingFolder?(e.className="vo-ws",e.innerHTML=`${s("reopen",d("web_visuobject_ws_reopen",this.pendingFolder.name),"text-button primary")}${s("switch",d("web_visuobject_ws_switch"),"text-button")}`):se(rt)==="1"?(e.className="vo-ws",e.innerHTML=s("open",d("web_visuobject_ws_choose"),"text-button",d("web_visuobject_ws_hint"))):(e.className="vo-ws ask",e.innerHTML=`

${b(d("web_visuobject_ws_question"))}

${b(d("web_visuobject_ws_hint"))}

diff --git a/website/app/assets/projectZip-DuO6aDli.js b/website/app/assets/projectZip-BzqOppdo.js similarity index 99% rename from website/app/assets/projectZip-DuO6aDli.js rename to website/app/assets/projectZip-BzqOppdo.js index 958b183f..b8f26bfe 100644 --- a/website/app/assets/projectZip-DuO6aDli.js +++ b/website/app/assets/projectZip-BzqOppdo.js @@ -1 +1 @@ -import{p as Br,d as Er,a as mr,i as Gr,b as Qr,c as Vr,u as Lr,n as _r,o as pr,e as br,r as dr,f as re,s as ee}from"./objectApp-wBFGa9mb.js";import"./index-BJMBJyRW.js";var M=Uint8Array,K=Uint16Array,Tr=Int32Array,hr=new M([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),gr=new M([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),Sr=new M([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Wr=function(r,e){for(var n=new K(31),a=0;a<31;++a)n[a]=e+=1<>1|(F&21845)<<1;b=(b&52428)>>2|(b&13107)<<2,b=(b&61680)>>4|(b&3855)<<4,Cr[F]=((b&65280)>>8|(b&255)<<8)>>1}var V=(function(r,e,n){for(var a=r.length,f=0,v=new K(e);f>l]=c}else for(s=new K(a),f=0;f>15-r[f]);return s}),d=new M(288);for(var F=0;F<144;++F)d[F]=8;for(var F=144;F<256;++F)d[F]=9;for(var F=256;F<280;++F)d[F]=7;for(var F=280;F<288;++F)d[F]=8;var ir=new M(32);for(var F=0;F<32;++F)ir[F]=5;var ae=V(d,9,0),fe=V(d,9,1),ve=V(ir,5,0),te=V(ir,5,1),xr=function(r){for(var e=r[0],n=1;ne&&(e=r[n]);return e},X=function(r,e,n){var a=e/8|0;return(r[a]|r[a+1]<<8)>>(e&7)&n},yr=function(r,e){var n=e/8|0;return(r[n]|r[n+1]<<8|r[n+2]<<16)>>(e&7)},Ur=function(r){return(r+7)/8|0},lr=function(r,e,n){return(e==null||e<0)&&(e=0),(n==null||n>r.length)&&(n=r.length),new M(r.subarray(e,n))},oe=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],I=function(r,e,n){var a=new Error(e||oe[r]);if(a.code=r,Error.captureStackTrace&&Error.captureStackTrace(a,I),!n)throw a;return a},ie=function(r,e,n,a){var f=r.length,v=a?a.length:0;if(!f||e.f&&!e.l)return n||new M(0);var i=!n,s=i||e.i!=2,l=e.i;i&&(n=new M(f*3));var c=function(fr){var vr=n.length;if(fr>vr){var nr=new M(Math.max(vr*2,fr));nr.set(n),n=nr}},t=e.f||0,o=e.p||0,u=e.b||0,h=e.l,y=e.d,w=e.m,x=e.n,T=f*8;do{if(!h){t=X(r,o,1);var z=X(r,o+1,3);if(o+=3,z)if(z==1)h=fe,y=te,w=9,x=5;else if(z==2){var U=X(r,o,31)+257,A=X(r,o+10,15)+4,m=U+X(r,o+5,31)+1;o+=14;for(var g=new M(m),B=new M(19),j=0;j>4;if(C<16)g[j++]=C;else{var E=0,k=0;for(C==16?(k=3+X(r,o,3),o+=2,E=g[j-1]):C==17?(k=3+X(r,o,7),o+=3):C==18&&(k=11+X(r,o,127),o+=7);k--;)g[j++]=E}}var W=g.subarray(0,U),J=g.subarray(U);w=xr(W),x=xr(J),h=V(W,w,1),y=V(J,x,1)}else I(1);else{var C=Ur(o)+4,O=r[C-4]|r[C-3]<<8,$=C+O;if($>f){l&&I(0);break}s&&c(u+O),n.set(r.subarray(C,$),u),e.b=u+=O,e.p=o=$*8,e.f=t;continue}if(o>T){l&&I(0);break}}s&&c(u+131072);for(var ar=(1<>4;if(o+=E&15,o>T){l&&I(0);break}if(E||I(2),q<256)n[u++]=q;else if(q==256){L=o,h=null;break}else{var H=q-254;if(q>264){var j=q-257,S=hr[j];H=X(r,o,(1<>4;G||I(3),o+=G&15;var J=ne[rr];if(rr>3){var S=gr[rr];J+=yr(r,o)&(1<T){l&&I(0);break}s&&c(u+131072);var er=u+H;if(u>8},tr=function(r,e,n){n<<=e&7;var a=e/8|0;r[a]|=n,r[a+1]|=n>>8,r[a+2]|=n>>16},Fr=function(r,e){for(var n=[],a=0;au&&(u=v[a].s);var h=new K(u+1),y=Or(n[t-1],h,0);if(y>e){var a=0,w=0,x=y-e,T=1<e)w+=T-(1<>=x;w>0;){var C=v[a].s;h[C]=0&&w;--a){var O=v[a].s;h[O]==e&&(--h[O],++w)}y=e}return{t:new M(h),l:y}},Or=function(r,e,n){return r.s==-1?Math.max(Or(r.l,e,n+1),Or(r.r,e,n+1)):e[r.s]=n},Nr=function(r){for(var e=r.length;e&&!r[--e];);for(var n=new K(++e),a=0,f=r[0],v=1,i=function(l){n[a++]=l},s=1;s<=e;++s)if(r[s]==f&&s!=e)++v;else{if(!f&&v>2){for(;v>138;v-=138)i(32754);v>2&&(i(v>10?v-11<<5|28690:v-3<<5|12305),v=0)}else if(v>3){for(i(f),--v;v>6;v-=6)i(8304);v>2&&(i(v-3<<5|8208),v=0)}for(;v--;)i(f);v=1,f=r[s]}return{c:n.subarray(0,a),n:e}},or=function(r,e){for(var n=0,a=0;a>8,r[f+2]=r[f]^255,r[f+3]=r[f+1]^255;for(var v=0;v4&&!B[Sr[D-1]];--D);var p=c+5<<3,Z=or(f,d)+or(v,ir)+i,P=or(f,u)+or(v,w)+i+14+3*D+or(A,B)+2*A[16]+3*A[17]+7*A[18];if(l>=0&&p<=Z&&p<=P)return Kr(e,t,r.subarray(l,l+c));var E,k,W,J;if(_(e,t,1+(P15&&(_(e,t,q[m]>>5&127),t+=q[m]>>12)}}else E=ae,k=d,W=ve,J=ir;for(var m=0;m255){var H=S>>18&31;tr(e,t,E[H+257]),t+=k[H+257],H>7&&(_(e,t,S>>23&31),t+=hr[H]);var G=S&31;tr(e,t,W[G]),t+=J[G],G>3&&(tr(e,t,S>>5&8191),t+=gr[G])}else tr(e,t,E[S]),t+=k[S]}return tr(e,t,E[256]),t+k[256]},le=new Tr([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),Rr=new M(0),se=function(r,e,n,a,f,v){var i=v.z||r.length,s=new M(a+i+5*(1+Math.ceil(i/7e3))+f),l=s.subarray(a,s.length-f),c=v.l,t=(v.r||0)&7;if(e){t&&(l[0]=v.r>>3);for(var o=le[e-1],u=o>>13,h=o&8191,y=(1<7e3||B>24576)&&(E>423||!c)){t=Dr(r,l,0,O,$,U,m,B,D,g-D,t),B=A=m=0,D=g;for(var k=0;k<286;++k)$[k]=0;for(var k=0;k<30;++k)U[k]=0}var W=2,J=0,ar=h,R=Z-P&32767;if(E>2&&p==C(g-R))for(var L=Math.min(u,E)-1,q=Math.min(32767,g),H=Math.min(258,E);R<=q&&--ar&&Z!=P;){if(r[g+W]==r[g+W-R]){for(var S=0;SW){if(W=S,J=R,S>L)break;for(var G=Math.min(R,S-2),rr=0,k=0;krr&&(rr=ur,P=er)}}}Z=P,P=w[Z],R+=Z-P&32767}if(J){O[B++]=268435456|Mr[W]<<18|Jr[J];var fr=Mr[W]&31,vr=Jr[J]&31;m+=hr[fr]+gr[vr],++$[257+fr],++U[vr],j=g+W,++A}else O[B++]=r[g],++$[r[g]]}}for(g=Math.max(g,j);g=i&&(l[t/8|0]=c,nr=i),t=Kr(l,t+1,r.subarray(g,nr))}v.i=i}return lr(s,0,a+Ur(t)+f)},ue=(function(){for(var r=new Int32Array(256),e=0;e<256;++e){for(var n=e,a=9;--a;)n=(n&1&&-306674912)^n>>>1;r[e]=n}return r})(),ce=function(){var r=-1;return{p:function(e){for(var n=r,a=0;a>>8;r=n},d:function(){return~r}}},he=function(r,e,n,a,f){if(!f&&(f={l:1},e.dictionary)){var v=e.dictionary.subarray(-32768),i=new M(v.length+r.length);i.set(v),i.set(r,v.length),r=i,f.w=v.length}return se(r,e.level==null?6:e.level,e.mem==null?f.l?Math.ceil(Math.max(8,Math.min(13,Math.log(r.length)))*1.5):20:12+e.mem,n,a,f)},Xr=function(r,e){var n={};for(var a in r)n[a]=r[a];for(var a in e)n[a]=e[a];return n},Q=function(r,e){return r[e]|r[e+1]<<8},Y=function(r,e){return(r[e]|r[e+1]<<8|r[e+2]<<16|r[e+3]<<24)>>>0},kr=function(r,e){return Y(r,e)+Y(r,e+4)*4294967296},N=function(r,e,n){for(;n;++e)r[e]=n,n>>>=8};function ge(r,e){return he(r,e||{},0,0)}function we(r,e){return ie(r,{i:2},e&&e.out,e&&e.dictionary)}var Yr=function(r,e,n,a){for(var f in r){var v=r[f],i=e+f,s=a;Array.isArray(v)&&(s=Xr(a,v[1]),v=v[0]),v instanceof M?n[i]=[v,s]:(n[i+="/"]=[new M(0),s],Yr(v,i,n,a))}},Ir=typeof TextEncoder<"u"&&new TextEncoder,Ar=typeof TextDecoder<"u"&&new TextDecoder,me=0;try{Ar.decode(Rr,{stream:!0}),me=1}catch{}var xe=function(r){for(var e="",n=0;;){var a=r[n++],f=(a>127)+(a>223)+(a>239);if(n+f>r.length)return{s:e,r:lr(r,n-1)};f?f==3?(a=((a&15)<<18|(r[n++]&63)<<12|(r[n++]&63)<<6|r[n++]&63)-65536,e+=String.fromCharCode(55296|a>>10,56320|a&1023)):f&1?e+=String.fromCharCode((a&31)<<6|r[n++]&63):e+=String.fromCharCode((a&15)<<12|(r[n++]&63)<<6|r[n++]&63):e+=String.fromCharCode(a)}};function cr(r,e){var n;if(Ir)return Ir.encode(r);for(var a=r.length,f=new M(r.length+(r.length>>1)),v=0,i=function(c){f[v++]=c},n=0;nf.length){var s=new M(v+8+(a-n<<1));s.set(f),f=s}var l=r.charCodeAt(n);l<128||e?i(l):l<2048?(i(192|l>>6),i(128|l&63)):l>55295&&l<57344?(l=65536+(l&1047552)|r.charCodeAt(++n)&1023,i(240|l>>18),i(128|l>>12&63),i(128|l>>6&63),i(128|l&63)):(i(224|l>>12),i(128|l>>6&63),i(128|l&63))}return lr(f,0,v)}function jr(r,e){if(e){for(var n="",a=0;a65535&&I(9),e+=a+4}return e},Pr=function(r,e,n,a,f,v,i,s){var l=a.length,c=n.extra,t=s&&s.length,o=zr(c);N(r,e,i!=null?33639248:67324752),e+=4,i!=null&&(r[e++]=20,r[e++]=n.os),r[e]=20,e+=2,r[e++]=n.flag<<1|(v<0&&8),r[e++]=f&&8,r[e++]=n.compression&255,r[e++]=n.compression>>8;var u=new Date(n.mtime==null?Date.now():n.mtime),h=u.getFullYear()-1980;if((h<0||h>119)&&I(10),N(r,e,h<<25|u.getMonth()+1<<21|u.getDate()<<16|u.getHours()<<11|u.getMinutes()<<5|u.getSeconds()>>1),e+=4,v!=-1&&(N(r,e,n.crc),N(r,e+4,v<0?-v-2:v),N(r,e+8,n.size)),N(r,e+12,l),N(r,e+14,o),e+=16,i!=null&&(N(r,e,t),N(r,e+6,n.attrs),N(r,e+10,i),e+=14),r.set(a,e),e+=l,o)for(var y in c){var w=c[y],x=w.length;N(r,e,+y),N(r,e+2,x),r.set(w,e+4),e+=4+x}return t&&(r.set(s,e),e+=t),e},Se=function(r,e,n,a,f){N(r,e,101010256),N(r,e+8,n),N(r,e+10,n),N(r,e+12,a),N(r,e+16,f)};function Me(r,e){e||(e={});var n={},a=[];Yr(r,"",n,e);var f=0,v=0;for(var i in n){var s=n[i],l=s[0],c=s[1],t=c.level==0?0:8,o=cr(i),u=o.length,h=c.comment,y=h&&cr(h),w=y&&y.length,x=zr(c.extra);u>65535&&I(11);var T=t?ge(l,c):l,z=T.length,C=ce();C.p(l),a.push(Xr(c,{size:l.length,crc:C.d(),c:T,f:o,m:y,u:u!=i.length||y&&h.length!=w,o:f,compression:t})),f+=30+u+x+z,v+=76+2*(u+x)+(w||0)+z}for(var O=new M(v+22),$=f,U=v-f,A=0;A65558)&&I(13);var f=Q(r,a+8);if(!f)return{};var v=Y(r,a+16),i=v==4294967295||f==65535;if(i){var s=Y(r,a-12);i=Y(r,s)==101075792,i&&(f=Y(r,s+32),v=Y(r,s+48))}for(var l=0;l|]/g,"_")||"Projekt",n={};for(const l of r.files)n[`${e}/${br(l.path)}`]=new Uint8Array(cr(l.text));const a=[...r.packages.map(l=>`${e}/${dr(l)}/${re(l).replace(/\./g,"/")}/`),...ee(r).map(l=>`${e}/${l}/`)];for(const l of a)Object.keys(n).some(c=>c.startsWith(l))||(n[l.replace(/\/\/$/,"/")]=new Uint8Array);return(r.uml&&Object.keys(r.uml).length||(f=r.notes)!=null&&f.length||(v=r.objects)!=null&&v.length)&&(n[`${e}/${$r}`]=new Uint8Array(cr(JSON.stringify({format:"visuobject",version:1,uml:r.uml??{},...(i=r.notes)!=null&&i.length?{notes:r.notes}:{},...(s=r.objects)!=null&&s.length?{objects:r.objects}:{}},null,2)))),Me(n,{level:6})}function ze(r,e){var c;const n=Ce(r),a=Object.entries(n).filter(([t])=>/\.java$/i.test(t)&&!t.startsWith("__MACOSX/")).map(([t,o])=>({name:t,text:jr(o)})),f=new Set(Object.keys(n).map(t=>t.split("/")[0])),v=f.size===1&&Object.keys(n).some(t=>t.includes("/"))?[...f][0]:e,i=v!==e,s=Br(v,[]);for(const t of a){const o=Br(v,[{name:t.name.slice(t.name.lastIndexOf("/")+1),text:t.text}]).files[0],u=t.name.split("/").slice(i?1:0,-1),h=Er(o.text).split(".").filter(Boolean),w=u.slice(u.length-h.length).join("/")===h.join("/")?u.slice(0,u.length-h.length).join("/"):"",x=w&&w!==mr&&w.split("/").every(Gr)&&!w.includes(":")?w:mr,T=Qr(Vr(x,Er(o.text)),o.path.slice(o.path.lastIndexOf("/")+1));s.files=[...s.files.filter(z=>z.path!==T),{...o,path:T}],x!==mr&&!((c=s.sourceFolders)!=null&&c.includes(x))&&(s.sourceFolders=[...s.sourceFolders??[],x])}const l=Object.entries(n).find(([t])=>t===$r||t.endsWith(`/${$r}`));if(l)try{const t=JSON.parse(jr(l[1])),o=Lr(t.uml);o&&(s.uml=o);const u=_r(t.notes);u&&(s.notes=u);const h=pr(t.objects);h&&(s.objects=h)}catch{}return s}export{ze as projectFromZip,je as projectToZip}; +import{p as Br,d as Er,a as mr,i as Gr,b as Qr,c as Vr,u as Lr,n as _r,o as pr,e as br,r as dr,f as re,s as ee}from"./objectApp-JyBNWSS3.js";import"./index-xN_dxLEc.js";var M=Uint8Array,K=Uint16Array,Tr=Int32Array,hr=new M([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),gr=new M([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),Sr=new M([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Wr=function(r,e){for(var n=new K(31),a=0;a<31;++a)n[a]=e+=1<>1|(F&21845)<<1;b=(b&52428)>>2|(b&13107)<<2,b=(b&61680)>>4|(b&3855)<<4,Cr[F]=((b&65280)>>8|(b&255)<<8)>>1}var V=(function(r,e,n){for(var a=r.length,f=0,v=new K(e);f>l]=c}else for(s=new K(a),f=0;f>15-r[f]);return s}),d=new M(288);for(var F=0;F<144;++F)d[F]=8;for(var F=144;F<256;++F)d[F]=9;for(var F=256;F<280;++F)d[F]=7;for(var F=280;F<288;++F)d[F]=8;var ir=new M(32);for(var F=0;F<32;++F)ir[F]=5;var ae=V(d,9,0),fe=V(d,9,1),ve=V(ir,5,0),te=V(ir,5,1),xr=function(r){for(var e=r[0],n=1;ne&&(e=r[n]);return e},X=function(r,e,n){var a=e/8|0;return(r[a]|r[a+1]<<8)>>(e&7)&n},yr=function(r,e){var n=e/8|0;return(r[n]|r[n+1]<<8|r[n+2]<<16)>>(e&7)},Ur=function(r){return(r+7)/8|0},lr=function(r,e,n){return(e==null||e<0)&&(e=0),(n==null||n>r.length)&&(n=r.length),new M(r.subarray(e,n))},oe=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],I=function(r,e,n){var a=new Error(e||oe[r]);if(a.code=r,Error.captureStackTrace&&Error.captureStackTrace(a,I),!n)throw a;return a},ie=function(r,e,n,a){var f=r.length,v=a?a.length:0;if(!f||e.f&&!e.l)return n||new M(0);var i=!n,s=i||e.i!=2,l=e.i;i&&(n=new M(f*3));var c=function(fr){var vr=n.length;if(fr>vr){var nr=new M(Math.max(vr*2,fr));nr.set(n),n=nr}},t=e.f||0,o=e.p||0,u=e.b||0,h=e.l,y=e.d,w=e.m,x=e.n,T=f*8;do{if(!h){t=X(r,o,1);var z=X(r,o+1,3);if(o+=3,z)if(z==1)h=fe,y=te,w=9,x=5;else if(z==2){var U=X(r,o,31)+257,A=X(r,o+10,15)+4,m=U+X(r,o+5,31)+1;o+=14;for(var g=new M(m),B=new M(19),j=0;j>4;if(C<16)g[j++]=C;else{var E=0,k=0;for(C==16?(k=3+X(r,o,3),o+=2,E=g[j-1]):C==17?(k=3+X(r,o,7),o+=3):C==18&&(k=11+X(r,o,127),o+=7);k--;)g[j++]=E}}var W=g.subarray(0,U),J=g.subarray(U);w=xr(W),x=xr(J),h=V(W,w,1),y=V(J,x,1)}else I(1);else{var C=Ur(o)+4,O=r[C-4]|r[C-3]<<8,$=C+O;if($>f){l&&I(0);break}s&&c(u+O),n.set(r.subarray(C,$),u),e.b=u+=O,e.p=o=$*8,e.f=t;continue}if(o>T){l&&I(0);break}}s&&c(u+131072);for(var ar=(1<>4;if(o+=E&15,o>T){l&&I(0);break}if(E||I(2),q<256)n[u++]=q;else if(q==256){L=o,h=null;break}else{var H=q-254;if(q>264){var j=q-257,S=hr[j];H=X(r,o,(1<>4;G||I(3),o+=G&15;var J=ne[rr];if(rr>3){var S=gr[rr];J+=yr(r,o)&(1<T){l&&I(0);break}s&&c(u+131072);var er=u+H;if(u>8},tr=function(r,e,n){n<<=e&7;var a=e/8|0;r[a]|=n,r[a+1]|=n>>8,r[a+2]|=n>>16},Fr=function(r,e){for(var n=[],a=0;au&&(u=v[a].s);var h=new K(u+1),y=Or(n[t-1],h,0);if(y>e){var a=0,w=0,x=y-e,T=1<e)w+=T-(1<>=x;w>0;){var C=v[a].s;h[C]=0&&w;--a){var O=v[a].s;h[O]==e&&(--h[O],++w)}y=e}return{t:new M(h),l:y}},Or=function(r,e,n){return r.s==-1?Math.max(Or(r.l,e,n+1),Or(r.r,e,n+1)):e[r.s]=n},Nr=function(r){for(var e=r.length;e&&!r[--e];);for(var n=new K(++e),a=0,f=r[0],v=1,i=function(l){n[a++]=l},s=1;s<=e;++s)if(r[s]==f&&s!=e)++v;else{if(!f&&v>2){for(;v>138;v-=138)i(32754);v>2&&(i(v>10?v-11<<5|28690:v-3<<5|12305),v=0)}else if(v>3){for(i(f),--v;v>6;v-=6)i(8304);v>2&&(i(v-3<<5|8208),v=0)}for(;v--;)i(f);v=1,f=r[s]}return{c:n.subarray(0,a),n:e}},or=function(r,e){for(var n=0,a=0;a>8,r[f+2]=r[f]^255,r[f+3]=r[f+1]^255;for(var v=0;v4&&!B[Sr[D-1]];--D);var p=c+5<<3,Z=or(f,d)+or(v,ir)+i,P=or(f,u)+or(v,w)+i+14+3*D+or(A,B)+2*A[16]+3*A[17]+7*A[18];if(l>=0&&p<=Z&&p<=P)return Kr(e,t,r.subarray(l,l+c));var E,k,W,J;if(_(e,t,1+(P15&&(_(e,t,q[m]>>5&127),t+=q[m]>>12)}}else E=ae,k=d,W=ve,J=ir;for(var m=0;m255){var H=S>>18&31;tr(e,t,E[H+257]),t+=k[H+257],H>7&&(_(e,t,S>>23&31),t+=hr[H]);var G=S&31;tr(e,t,W[G]),t+=J[G],G>3&&(tr(e,t,S>>5&8191),t+=gr[G])}else tr(e,t,E[S]),t+=k[S]}return tr(e,t,E[256]),t+k[256]},le=new Tr([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),Rr=new M(0),se=function(r,e,n,a,f,v){var i=v.z||r.length,s=new M(a+i+5*(1+Math.ceil(i/7e3))+f),l=s.subarray(a,s.length-f),c=v.l,t=(v.r||0)&7;if(e){t&&(l[0]=v.r>>3);for(var o=le[e-1],u=o>>13,h=o&8191,y=(1<7e3||B>24576)&&(E>423||!c)){t=Dr(r,l,0,O,$,U,m,B,D,g-D,t),B=A=m=0,D=g;for(var k=0;k<286;++k)$[k]=0;for(var k=0;k<30;++k)U[k]=0}var W=2,J=0,ar=h,R=Z-P&32767;if(E>2&&p==C(g-R))for(var L=Math.min(u,E)-1,q=Math.min(32767,g),H=Math.min(258,E);R<=q&&--ar&&Z!=P;){if(r[g+W]==r[g+W-R]){for(var S=0;SW){if(W=S,J=R,S>L)break;for(var G=Math.min(R,S-2),rr=0,k=0;krr&&(rr=ur,P=er)}}}Z=P,P=w[Z],R+=Z-P&32767}if(J){O[B++]=268435456|Mr[W]<<18|Jr[J];var fr=Mr[W]&31,vr=Jr[J]&31;m+=hr[fr]+gr[vr],++$[257+fr],++U[vr],j=g+W,++A}else O[B++]=r[g],++$[r[g]]}}for(g=Math.max(g,j);g=i&&(l[t/8|0]=c,nr=i),t=Kr(l,t+1,r.subarray(g,nr))}v.i=i}return lr(s,0,a+Ur(t)+f)},ue=(function(){for(var r=new Int32Array(256),e=0;e<256;++e){for(var n=e,a=9;--a;)n=(n&1&&-306674912)^n>>>1;r[e]=n}return r})(),ce=function(){var r=-1;return{p:function(e){for(var n=r,a=0;a>>8;r=n},d:function(){return~r}}},he=function(r,e,n,a,f){if(!f&&(f={l:1},e.dictionary)){var v=e.dictionary.subarray(-32768),i=new M(v.length+r.length);i.set(v),i.set(r,v.length),r=i,f.w=v.length}return se(r,e.level==null?6:e.level,e.mem==null?f.l?Math.ceil(Math.max(8,Math.min(13,Math.log(r.length)))*1.5):20:12+e.mem,n,a,f)},Xr=function(r,e){var n={};for(var a in r)n[a]=r[a];for(var a in e)n[a]=e[a];return n},Q=function(r,e){return r[e]|r[e+1]<<8},Y=function(r,e){return(r[e]|r[e+1]<<8|r[e+2]<<16|r[e+3]<<24)>>>0},kr=function(r,e){return Y(r,e)+Y(r,e+4)*4294967296},N=function(r,e,n){for(;n;++e)r[e]=n,n>>>=8};function ge(r,e){return he(r,e||{},0,0)}function we(r,e){return ie(r,{i:2},e&&e.out,e&&e.dictionary)}var Yr=function(r,e,n,a){for(var f in r){var v=r[f],i=e+f,s=a;Array.isArray(v)&&(s=Xr(a,v[1]),v=v[0]),v instanceof M?n[i]=[v,s]:(n[i+="/"]=[new M(0),s],Yr(v,i,n,a))}},Ir=typeof TextEncoder<"u"&&new TextEncoder,Ar=typeof TextDecoder<"u"&&new TextDecoder,me=0;try{Ar.decode(Rr,{stream:!0}),me=1}catch{}var xe=function(r){for(var e="",n=0;;){var a=r[n++],f=(a>127)+(a>223)+(a>239);if(n+f>r.length)return{s:e,r:lr(r,n-1)};f?f==3?(a=((a&15)<<18|(r[n++]&63)<<12|(r[n++]&63)<<6|r[n++]&63)-65536,e+=String.fromCharCode(55296|a>>10,56320|a&1023)):f&1?e+=String.fromCharCode((a&31)<<6|r[n++]&63):e+=String.fromCharCode((a&15)<<12|(r[n++]&63)<<6|r[n++]&63):e+=String.fromCharCode(a)}};function cr(r,e){var n;if(Ir)return Ir.encode(r);for(var a=r.length,f=new M(r.length+(r.length>>1)),v=0,i=function(c){f[v++]=c},n=0;nf.length){var s=new M(v+8+(a-n<<1));s.set(f),f=s}var l=r.charCodeAt(n);l<128||e?i(l):l<2048?(i(192|l>>6),i(128|l&63)):l>55295&&l<57344?(l=65536+(l&1047552)|r.charCodeAt(++n)&1023,i(240|l>>18),i(128|l>>12&63),i(128|l>>6&63),i(128|l&63)):(i(224|l>>12),i(128|l>>6&63),i(128|l&63))}return lr(f,0,v)}function jr(r,e){if(e){for(var n="",a=0;a65535&&I(9),e+=a+4}return e},Pr=function(r,e,n,a,f,v,i,s){var l=a.length,c=n.extra,t=s&&s.length,o=zr(c);N(r,e,i!=null?33639248:67324752),e+=4,i!=null&&(r[e++]=20,r[e++]=n.os),r[e]=20,e+=2,r[e++]=n.flag<<1|(v<0&&8),r[e++]=f&&8,r[e++]=n.compression&255,r[e++]=n.compression>>8;var u=new Date(n.mtime==null?Date.now():n.mtime),h=u.getFullYear()-1980;if((h<0||h>119)&&I(10),N(r,e,h<<25|u.getMonth()+1<<21|u.getDate()<<16|u.getHours()<<11|u.getMinutes()<<5|u.getSeconds()>>1),e+=4,v!=-1&&(N(r,e,n.crc),N(r,e+4,v<0?-v-2:v),N(r,e+8,n.size)),N(r,e+12,l),N(r,e+14,o),e+=16,i!=null&&(N(r,e,t),N(r,e+6,n.attrs),N(r,e+10,i),e+=14),r.set(a,e),e+=l,o)for(var y in c){var w=c[y],x=w.length;N(r,e,+y),N(r,e+2,x),r.set(w,e+4),e+=4+x}return t&&(r.set(s,e),e+=t),e},Se=function(r,e,n,a,f){N(r,e,101010256),N(r,e+8,n),N(r,e+10,n),N(r,e+12,a),N(r,e+16,f)};function Me(r,e){e||(e={});var n={},a=[];Yr(r,"",n,e);var f=0,v=0;for(var i in n){var s=n[i],l=s[0],c=s[1],t=c.level==0?0:8,o=cr(i),u=o.length,h=c.comment,y=h&&cr(h),w=y&&y.length,x=zr(c.extra);u>65535&&I(11);var T=t?ge(l,c):l,z=T.length,C=ce();C.p(l),a.push(Xr(c,{size:l.length,crc:C.d(),c:T,f:o,m:y,u:u!=i.length||y&&h.length!=w,o:f,compression:t})),f+=30+u+x+z,v+=76+2*(u+x)+(w||0)+z}for(var O=new M(v+22),$=f,U=v-f,A=0;A65558)&&I(13);var f=Q(r,a+8);if(!f)return{};var v=Y(r,a+16),i=v==4294967295||f==65535;if(i){var s=Y(r,a-12);i=Y(r,s)==101075792,i&&(f=Y(r,s+32),v=Y(r,s+48))}for(var l=0;l|]/g,"_")||"Projekt",n={};for(const l of r.files)n[`${e}/${br(l.path)}`]=new Uint8Array(cr(l.text));const a=[...r.packages.map(l=>`${e}/${dr(l)}/${re(l).replace(/\./g,"/")}/`),...ee(r).map(l=>`${e}/${l}/`)];for(const l of a)Object.keys(n).some(c=>c.startsWith(l))||(n[l.replace(/\/\/$/,"/")]=new Uint8Array);return(r.uml&&Object.keys(r.uml).length||(f=r.notes)!=null&&f.length||(v=r.objects)!=null&&v.length)&&(n[`${e}/${$r}`]=new Uint8Array(cr(JSON.stringify({format:"visuobject",version:1,uml:r.uml??{},...(i=r.notes)!=null&&i.length?{notes:r.notes}:{},...(s=r.objects)!=null&&s.length?{objects:r.objects}:{}},null,2)))),Me(n,{level:6})}function ze(r,e){var c;const n=Ce(r),a=Object.entries(n).filter(([t])=>/\.java$/i.test(t)&&!t.startsWith("__MACOSX/")).map(([t,o])=>({name:t,text:jr(o)})),f=new Set(Object.keys(n).map(t=>t.split("/")[0])),v=f.size===1&&Object.keys(n).some(t=>t.includes("/"))?[...f][0]:e,i=v!==e,s=Br(v,[]);for(const t of a){const o=Br(v,[{name:t.name.slice(t.name.lastIndexOf("/")+1),text:t.text}]).files[0],u=t.name.split("/").slice(i?1:0,-1),h=Er(o.text).split(".").filter(Boolean),w=u.slice(u.length-h.length).join("/")===h.join("/")?u.slice(0,u.length-h.length).join("/"):"",x=w&&w!==mr&&w.split("/").every(Gr)&&!w.includes(":")?w:mr,T=Qr(Vr(x,Er(o.text)),o.path.slice(o.path.lastIndexOf("/")+1));s.files=[...s.files.filter(z=>z.path!==T),{...o,path:T}],x!==mr&&!((c=s.sourceFolders)!=null&&c.includes(x))&&(s.sourceFolders=[...s.sourceFolders??[],x])}const l=Object.entries(n).find(([t])=>t===$r||t.endsWith(`/${$r}`));if(l)try{const t=JSON.parse(jr(l[1])),o=Lr(t.uml);o&&(s.uml=o);const u=_r(t.notes);u&&(s.notes=u);const h=pr(t.objects);h&&(s.objects=h)}catch{}return s}export{ze as projectFromZip,je as projectToZip}; diff --git a/website/app/assets/robot3d-Dz8gQ3hd.js b/website/app/assets/robot3d-ClismEE4.js similarity index 99% rename from website/app/assets/robot3d-Dz8gQ3hd.js rename to website/app/assets/robot3d-ClismEE4.js index d022eb3b..c3fd8bc9 100644 --- a/website/app/assets/robot3d-Dz8gQ3hd.js +++ b/website/app/assets/robot3d-ClismEE4.js @@ -1,4 +1,4 @@ -var gl=Object.defineProperty;var _l=(i,t,e)=>t in i?gl(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var le=(i,t,e)=>_l(i,typeof t!="symbol"?t+"":t,e);import{C as rn,L as oo}from"./index-BJMBJyRW.js";/** +var gl=Object.defineProperty;var _l=(i,t,e)=>t in i?gl(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var le=(i,t,e)=>_l(i,typeof t!="symbol"?t+"":t,e);import{C as rn,L as oo}from"./index-xN_dxLEc.js";/** * @license * Copyright 2010-2025 Three.js Authors * SPDX-License-Identifier: MIT diff --git a/website/app/index.html b/website/app/index.html index 4a836848..a89df73c 100644 --- a/website/app/index.html +++ b/website/app/index.html @@ -6,7 +6,7 @@ VisuStruct Web - +